代码之家  ›  专栏  ›  技术社区  ›  Dmitry Katkevich

无法使用各种lambda表达式初始化std::variant

  •  15
  • Dmitry Katkevich  · 技术社区  · 9 年前

    std::variant, lambdas std::future ,当我试图将它们组合在一起时,得到了非常奇怪的结果。以下是示例:

    using variant_t = std::variant<
        std::function<std::future<void>(int)>,
        std::function<void(int)>
    >;
    auto f1 = [](int) { return std::async([] { return 1; }); };
    auto f2 = [](int) { return std::async([] {  }); };
    
    variant_t v1(std::move(f1)); // !!! why DOES this one compile when it SHOULDN'T?
    auto idx1 = v1.index(); //equals 1. WHY?
    
    variant_t v2(std::move(f2)); // !!! why DOESN'T this one compile when it SHOULD?
    

    错误C2665'std::variant<标准::函数<标准::未来<void> (int)>,标准::函数<void(int)>>::变量”:2个重载中没有一个 无法转换所有参数类型

    variant 返回的项目签名 void int

    using variant_t = std::variant<
        std::function<std::future<int>(int)>,
        std::function<int(int)>
    >;
    
    variant_t v1(std::move(f1)); // COMPILES (like it should)
    auto idx1 = v1.index(); // equals 0
    
    variant_t v2(std::move(f2)); // DOESN'T compile (like it should)
    

    这到底是怎么回事?为什么是 std::future<void> 这么特别?

    1 回复  |  直到 9 年前
        1
  •  16
  •   Columbo    9 年前

    variant 的转换构造函数模板使用重载解析来确定构造的对象应该具有哪种类型。特别是,这意味着如果对这些类型的转换同样好,那么构造函数就不起作用;在您的情况下,如果恰好是 std::function

    那么什么时候 function<...> 可从给定参数构造?从C++14开始,如果参数可以使用参数类型调用,并且生成的类型为 convertible to the return type void ,任何事情都会发生(如 any expression can be converted to void with static_cast function 返回 无效的 function<void(int)> 适用于 f1 future<int> 不转换为 future<void> ; 因此只有 函数(<);void(int)>

    未来<void> ,可转换为两者 未来<void> 无效的 如上所述,这会导致 作用 专业化是可行的,这就是为什么 变种 无法决定要构造哪个。

    最后,如果您将返回类型调整为 int 无效的