【问题标题】:std::variant with overloaded lambdas, alternative with MSVC?带有重载 lambda 的 std::variant,替代 MSVC?
【发布时间】:2018-05-24 12:59:47
【问题描述】:

cppreference 重载“技巧”可以通过模板化的operator() 重载访问每个变体,该技巧无法使用 Visual C++ 编译器进行编译。代码 sn-p 可以在here 找到,使用 clang 或 gcc 编译时可以正常执行。

但是,这不能使用 MSVC (see on godbolt) 编译:

template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

它抛出各种错误并最终失败:

warning C4346: 'Ts::()': dependent name is not a type  
note: prefix with 'typename' to indicate a type  
note: see reference to class template instantiation 'overloaded<Ts...>' being compiled  
error C2143: syntax error: missing ';' before '...'  
error C2059: syntax error: '...'  
error C2238: unexpected token(s) preceding ';'  
error C2988: unrecognizable template declaration/definition  
error C2143: syntax error: missing ')' before '...'  
error C2143: syntax error: missing ';' before '...'  
error C2365: 'Ts': redefinition; previous definition was 'template parameter'  
note: see declaration of 'Ts'  
error C2059: syntax error: ')'  
error C2059: syntax error: '->'  
error C2065: 'Ts': undeclared identifier  
error C3544: 'Ts': parameter pack expects a type template argument  

还有其他选择吗?我是否缺少编译器的选项?

【问题讨论】:

  • @Someprogrammerdude 但这是一个虚假错误——MSVC 似乎认为这是() 的转换运算符,这确实不是一种类型。
  • 这对我来说在 15.7.1 版本上编译得很好
  • Godbolt 使用的是编译器版本 19.10.25017,而我的 15.7.1 的编译器版本是 19.14.26428.1
  • 哈.. 好的,这是编译器版本问题,它确实适用于最新版本。我会看看我是否可以更新运行它的机器。与此同时,它仍然强调语法错误。

标签: c++ visual-c++ c++17


【解决方案1】:
template<class...Ts>
struct overloaded_t {};

template<class T0>
struct overloaded_t<T0>:T0 {
  using T0::operator();
  overloaded_t(T0 t0):T0(std::move(t0)) {}
};
template<class T0, class T1, class...Ts>
struct overloaded_t<T0, T1, Ts...>:T0, overloaded_t<T1, Ts...> {
  using T0::operator();
  using overloaded_t<T1, Ts...>::operator();
  overloaded_t(T0 t0, T1 t1, Ts... ts):
    T0(std::move(t0)),
    overloaded_t<T1, Ts...>(std::move(t1), std::move(ts)...)
  {}
};

template<class...Ts>
overloaded_t<Ts...> overloaded(Ts...ts){ return {std::move(ts)...}; }

或升级到最新的编译器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多