T.C. gave a clever solution here which used this object:
template<class... Ts> struct overload : Ts... { using Ts::operator()...; };
template<class... Ts> overload(Ts...) -> overload<Ts...>;
struct fallback_t { template<class T> fallback_t(T&&) {} };
Unfortunately I can't get that to compile in Visual Studio 2017. I get the errors:
1> warning C4346: 'Ts::()': dependent name is not a type
1> note: prefix with 'typename' to indicate a type
1> note: see reference to class template instantiation 'owner::overload' being compiled
1> error C2143: syntax error: missing ';' before '...'
1> error C2059: syntax error: '...'
1> error C2238: unexpected token(s) preceding ';'
1> error C2988: unrecognizable template declaration/definition
1> error C2143: syntax error: missing ')' before '...'
1> error C2143: syntax error: missing ';' before '...'
1> error C2365: 'Ts': redefinition; previous definition was 'template parameter'
1> note: see declaration of 'Ts'
1> error C2238: unexpected token(s) preceding ';'
1> error C2059: syntax error: '...'
1> error C2059: syntax error: ')'
1> error C2955: 'owner::overload': use of class template requires template argument list
1> note: see declaration of 'owner::overload'
1> error C2664: 'void owner::bar::
::operator ()(owner::fallback_t) const': cannot convert argument 1 from 'owner::fallback_t' to 'owner::fallback_t'
1> note: use of undefined type 'owner::fallback_t'
1> note: see declaration of 'owner::fallback_t'
1> error C2672: 'owner::findObject': no matching overloaded function found
1> error C2780: 'void owner::findObject(int,const T &)': expects 2 arguments - 1 provided
1> note: see declaration of 'owner::findObject'
Is there any trickery that I can do to make Visual Studio respect the variadic template in?
You can try to compile in c++17 mode with
/std::c++17
as @S.M. has noted; note that some C++17 features can break existing code. In addition as @milesbudnek has noted, as of today MSVC doesn't support the requried features.If you cannot use C++17 mode you can implement this in c++14 in this SO answer.
I'd make a few changes:
In C++14, it would be something like:
Demo
This is dependent on three separate C++17 features:
The usual pre-C++17 workaround for the first is recursive inheritance (forwarding omitted for simplicity):
The constructors are needed if the compiler doesn't support aggregates with base classes; the
make_overload
is needed if the compiler doesn't support template argument deduction for class templates.It is valid in C++17 only. Try to compile it in Visual Studio 2017 with the flag
/std:c++17
under Project -> Properties -> C++ -> Language. Please note, C++17 is available starting from Visual Studio 2017.3.