连词模板不会短路
Conjuction template doesn't short circuit
我希望能够评估一个函数是否接受一个 int 类型的参数,以及它是否 returns void。为此,我使用了 std::conjunction
,因为我认为它应该短路而不是计算第二个格式错误的表达式,以防函数不能用一个 int 类型的参数调用,但出于某种原因我得到了一个编译器错误:
#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;
}
请注意,如果 oneArgVoid
未在 l3
上调用,则代码会编译。现场演示:https://godbolt.org/z/8BUfpT
我没有使用boost,所以无法使用mpl::eval_if
。但是我认为std::conjunction
应该是这里短路,我错了吗?
考虑到 HolyBlackCat 的建议,这里有一些更奇怪的东西:https://godbolt.org/z/2SUij-
似乎 std::conjunction
short-circuits 仅在类型的值上,类型本身仍然必须是 well-formed。所以这个: std::is_void<std::invoke_result_t<Function, int>>
在这里实际上是非法的。由于修改:
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>>;
};
它起作用了,因为 ill-formed 表达式现在在值变量中,这意味着它不会因为 short-circuit.
而被计算
我希望能够评估一个函数是否接受一个 int 类型的参数,以及它是否 returns void。为此,我使用了 std::conjunction
,因为我认为它应该短路而不是计算第二个格式错误的表达式,以防函数不能用一个 int 类型的参数调用,但出于某种原因我得到了一个编译器错误:
#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;
}
请注意,如果 oneArgVoid
未在 l3
上调用,则代码会编译。现场演示:https://godbolt.org/z/8BUfpT
我没有使用boost,所以无法使用mpl::eval_if
。但是我认为std::conjunction
应该是这里短路,我错了吗?
考虑到 HolyBlackCat 的建议,这里有一些更奇怪的东西:https://godbolt.org/z/2SUij-
似乎 std::conjunction
short-circuits 仅在类型的值上,类型本身仍然必须是 well-formed。所以这个: std::is_void<std::invoke_result_t<Function, int>>
在这里实际上是非法的。由于修改:
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>>;
};
它起作用了,因为 ill-formed 表达式现在在值变量中,这意味着它不会因为 short-circuit.
而被计算