为什么此 get_index 实现在 VS2017 上失败?
Why does this get_index implementation fail on VS2017?
巴里给了我们 :
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
因为我一直在使用 Xcode 9,它没有 std::variant
。但是,您可以从上面的 Godbolt MCVE 中看到,这也会影响 std::variant
的实现。我确信问题要么在上面的代码中,要么在编译器中。)
我敢打赌这是一个编译器错误。
我看到如果我写 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; }
我称它为 main()
,
foo<int, long, int, long long>();
在 main()
中声明以下变量也没问题
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()>
{ };
编译器抱怨但有不同的错误
example.cpp
(12): error C2440: 'initializing': cannot convert from 'initializer list' to 'std::variant...>'
(12): note: The target type has no constructors
(13): note: see reference to class template instantiation 'get_index>' being compiled
Compiler returned: 2
似乎,由于我无法理解的原因,编译器在 get_index
中看不到 std::variant<tag<Ts>...>
,作为具有所有方法的 std::variant
。
巴里给了我们
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
因为我一直在使用 Xcode 9,它没有 std::variant
。但是,您可以从上面的 Godbolt MCVE 中看到,这也会影响 std::variant
的实现。我确信问题要么在上面的代码中,要么在编译器中。)
我敢打赌这是一个编译器错误。
我看到如果我写 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; }
我称它为 main()
,
foo<int, long, int, long long>();
在 main()
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()>
{ };
编译器抱怨但有不同的错误
example.cpp
(12): error C2440: 'initializing': cannot convert from 'initializer list' to 'std::variant...>'
(12): note: The target type has no constructors
(13): note: see reference to class template instantiation 'get_index>' being compiled
Compiler returned: 2
似乎,由于我无法理解的原因,编译器在 get_index
中看不到 std::variant<tag<Ts>...>
,作为具有所有方法的 std::variant
。