【问题标题】:Conjuction template doesn't short circuit连接模板不短路
【发布时间】:2019-11-22 22:07:00
【问题描述】:

我希望能够评估一个函数是否接受一个 int 类型的参数,以及它是否返回 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-

【问题讨论】:

  • @HolyBlackCat 似乎没有按预期工作:godbolt.org/z/EL6Ci4 似乎 int 可以转换为 void? Determines whether Fn can be invoked with the arguments ArgTypes... to yield a result that is convertible to R.
  • 嗯,我的错。我应该先检查文档。
  • @HolyBlackCat 我不认为你错了,int 不能转换为 void:godbolt.org/z/zJxI94

标签: c++ templates c++17 short-circuiting


【解决方案1】:

似乎std::conjunction 仅在类型的值上短路,类型本身仍然必须是格式良好的。所以这个:std::is_void&lt;std::invoke_result_t&lt;Function, int&gt;&gt; 在这里实际上是非法的。由于修改:

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>>;
};

它可以工作,因为格式错误的表达式现在位于 value 变量中,这意味着它不会因为短路而被计算。

【讨论】:

    猜你喜欢
    • 2020-05-11
    • 2011-06-03
    • 1970-01-01
    • 1970-01-01
    • 2021-09-10
    • 2018-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多