【问题标题】:Why does this get_index implementation fail on VS2017?为什么这个 get_index 实现在 VS2017 上失败?
【发布时间】:2018-12-06 12:35:40
【问题描述】:

巴里给了我们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,因为我一直在使用 Xcode 9,它没有 std::variant。但是,你可以从上面的 Godbolt MCVE 中看到这个也会影响std::variant 的实现。我确信问题出在上面的代码中,或者在编译器中。)

【问题讨论】:

  • 代码没问题。编译器错误。
  • 一种解决方法是将表达式传送到变量模板中。
  • @Barry 这是一个不同的错误,因为{}} 包含一个不匹配的}
  • @Oktalist Ooooooooooooooooooooooooooooos
  • FWIW, it works 如果表达式被移动到 constexpr 类型的 std::size_t() 函数中,但不是 constexpr auto 函数(编译器无意义地声称使用了 auto 函数在定义之前)。

标签: c++ visual-studio visual-studio-2017 c++17 variant


【解决方案1】:

我打赌我的 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; }

我称它为 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):错误 C2440:“正在初始化”:无法从“初始化程序列表”转换为“std::variant...>”

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

(13):注意:请参阅正在编译的类模板实例化 'get_index>' 的参考

编译器返回:2

似乎,由于我无法理解的原因,编译器没有将std::variant&lt;tag&lt;Ts&gt;...&gt; 内部的get_index 视为具有所有方法的std::variant

【讨论】:

  • 同意。我不得不从原始问题的另一个答案中退回到if constexpr 链。对不起巴里!
  • @LightnessRacesinOrbit - 很遗憾,因为 Barry 的解决方案非常简单优雅。
  • 确实!虽然想到它,但我确实认为条件句更容易理解。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-10
  • 2021-05-01
  • 1970-01-01
相关资源
最近更新 更多