3

The cppreference overloaded "trick" where each variant can be visited through a templated operator() overload doesn't compile with the Visual C++ compiler. Code snippet can be found here and executes fine when compiled with clang or gcc.

However, this doesn't compile with MSVC (see on godbolt):

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

It throws various errors and ultimately fails:

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  

Is there an alternative? Am I missing options for the compiler?

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
Fluffy
  • 857
  • 1
  • 9
  • 20
  • 2
    @Someprogrammerdude but that's a bogus error -- MSVC seems to think that this is a conversion operator to `()`, which indeed is not quite a type. – Quentin May 24 '18 at 13:04
  • 3
    This compiles fine for me on version 15.7.1 – NathanOliver May 24 '18 at 13:06
  • 2
    Godbolt is using Compiler Version 19.10.25017 where my 15.7.1 has Compiler Version 19.14.26428.1 – NathanOliver May 24 '18 at 13:11
  • 1
    Ha.. Okay so it's a compiler version issue, it does work with the latest version. I'll see if I can update the machine this runs on. In the meantime it stills underlines the syntax as wrong. – Fluffy May 24 '18 at 13:20

1 Answers1

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)...}; }

or upgrade to latest compiler.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524