代码之家  ›  专栏  ›  技术社区  ›  Lightness Races in Orbit Shash316

为什么在VS2017上执行索引失败?

  •  6
  • Lightness Races in Orbit Shash316  · 技术社区  · 5 年前

    巴里给了我们 this gorgeous get_index for variants :

    template <typename> struct tag { };
    
    template <typename T, typename V>
    struct get_index;
    
    template <typename T, typename... Ts> 
    struct get_index<T, std::variant<Ts...>>
        : std::integral_constant<size_t, std::variant<tag<Ts>...>(tag<T>()).index()>
    { };
    

    使用方法如下:

    using V = variant<A, B, C>;
    constexpr const size_t N = get_index<B, V>::value;  // 1
    

    它在Clang(OSX)中工作得很好。

    但是在Visual Studio 2017中 I'm getting 下列内容:

    <source>(10): error C2039: 'index': is not a member of 'std::variant<tag<Ts>...>'
    <source>(10): note: see declaration of 'std::variant<tag<Ts>...>'
    <source>(11): note: see reference to class template instantiation 'get_index<T,std::variant<_Types...>>' being compiled
    Compiler returned: 2
    

    我不明白为什么。有什么想法吗?

    (完全公开:在我的项目中,我实际使用 mpark::variant 因为我一直在使用Xcode9,而不是 std::variant . 但是,您可以从上面的godbolt mcve中看到,这会影响 STD::变异型 也。我相信问题可能出在上面的代码中,也可能出在编译器中。)

    1 回复  |  直到 5 年前
        1
  •  2
  •   max66    5 年前

    我赌我的2美分那是一个编译器错误。

    我知道如果我写的话 main()

    std::cout << std::variant<tag<int>, tag<float>>{tag<float>{}}.index() << std::endl;
    

    编译器没有抱怨。

    如果我写一个模板函数,也不会抱怨

    template <typename T, typename ... Ts>
    void foo ()
     { std::cout << std::variant<tag<Ts>...>(tag<T>{}).index() << std::endl; }
    

    我叫它,从 主体()

    foo<int, long, int, long long>();
    

    在中声明以下变量没有问题 主体()

    std::integral_constant<std::size_t, std::variant<tag<int>, tag<float>>(tag<float>{}).index()>  ic;
    

    但是如果我改变 get_index 专门化如下(使用大括号而不是圆括号进行初始化)

    template <typename T, typename... Ts> 
    struct get_index<T, std::variant<Ts...>>
        : std::integral_constant<std::size_t, std::variant<tag<Ts>...>{tag<T>()}.index()>
     { };
    

    编译器抱怨,但有不同的错误

    实例CPP

    (12):错误C2440:“正在初始化”:无法从“初始值设定项列表”转换为“std::variant…>”

    (12):注意:目标类型没有构造函数

    (13):注意:参见正在编译的类模板实例化“get_index>”

    编译器返回:2

    看来,由于我无法理解的原因,编译器没有看到 std::variant<tag<Ts>...> 里面 获取索引 作为一个 std::variant 用所有的方法。