3 votes

Le modèle de conjonction n'est pas en court-circuit

Je veux pouvoir évaluer si une fonction accepte un argument de type int, et si elle renvoie void. À cette fin, j'ai utilisé std::conjunction car je pensais qu'il était censé court-circuiter et ne pas évaluer la deuxième expression mal formée au cas où la fonction ne serait pas appelable avec un argument de type int, mais pour une raison quelconque, j'obtiens une erreur du compilateur :

#include <iostream>
#include <type_traits>
template<typename Function>
struct oneArgVoid
{
    static constexpr bool value = std::conjunction_v<std::is_invocable<Function, int>, std::is_void<std::invoke_result_t<Function, int>>>;
};

int main()
{
    auto l1 = [](auto x) {};
    std::cout << oneArgVoid<decltype(l1)>::value << "\n";
    auto l2 = [](auto x) {return 1; };
    std::cout << oneArgVoid<decltype(l2)>::value << "\n";
    auto l3 = [](auto x, auto y) {};
    std::cout << oneArgVoid<decltype(l3)>::value << "\n";
    return 0;
}

Il convient de noter que si oneArgVoid n'est pas appelé sur l3 le code se compile. Démonstration en direct : https://godbolt.org/z/8BUfpT

Je n'utilise pas la fonction "boost", je ne peux donc pas l'utiliser. mpl::eval_if . Mais j'ai pensé que std::conjunction était censé faire un court-circuit à cet endroit, est-ce que je me trompe ?

Compte tenu de la suggestion de HolyBlackCat, voici quelque chose d'encore plus étrange : https://godbolt.org/z/2SUij-

1voto

lightxbulb Points 118

Il semble que std::conjunction ne court-circuite que les valeurs des types, les types eux-mêmes doivent toujours être bien formés. Voici donc ce qu'il en est : std::is_void<std::invoke_result_t<Function, int>> est en fait illégale à juste titre. En raison de cette modification :

template<typename Function>
struct argVoid
{
    static constexpr bool value = std::is_void_v<std::invoke_result_t<Function, int>>;
};

template<typename Function>
struct oneArgVoid
{
    static constexpr bool value = std::conjunction_v<std::is_invocable<Function, int>, argVoid<Function>>;
};

Cela fonctionne, car l'expression mal formée se trouve maintenant dans la variable value, ce qui signifie qu'elle n'est pas évaluée en raison du court-circuit.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X