Reputation: 391
In the code below, compiling of each of the template functions individually results in no error, but compiling error occurs when they are put together. Could anyone tell me why, and how to fix it?
#include "stdafx.h"
#include <iostream>
void f(int a, int b)
{
std::cout << "MyFunctionI(" << a << ',' << b << ")\n";
}
template <typename CALLABLE, typename... ARGS>
typename std::enable_if<std::is_void<std::result_of_t<CALLABLE(ARGS&&...)>>::value, int>::type
DoFunction(CALLABLE fn, ARGS&&... args)
{
fn(args...);
return 0;
}
template <typename CALLABLE, typename... ARGS>
typename std::enable_if<std::is_void<std::result_of_t<CALLABLE(ARGS&&...)>>::value, int>::type
DoFunction(const int flag, CALLABLE fn, ARGS&&... args)
{
fn(args...);
return 0;
}
int main()
{
int nId1 = DoFunction(f, 1, 2);
int nId2 = DoFunction(1111, f, 1, 2);
return 0;
}
The compiler is VC2015 and error messages is:
1>c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits(1469): error C2672: 'std::invoke': no matching overloaded function found
1> c:\projects_svn\ssrcontrol_svn\testtemplate1\testtemplate1\testtemplate1.cpp(31): note: see reference to class template instantiation 'std::result_of<int (int &&)>' being compiled
1>c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits(1469): error C2893: Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...)'
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits(1469): note: With the following template arguments:
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits(1469): note: '_Callable=std::ios_base::iostate'
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits(1469): note: '_Types={int}'
Additional information, if I do not use method overloading, i.e. use different names for the template function, the compiler reports no error.
Upvotes: 1
Views: 559
Reputation: 717
The way you are using std::result_of
on a template variadic function is valid in c++14 but not in c++11.
Citing the documentation here (source):
As formulated in C++11,
std::result_of
would fail to compile whenF(ArgTypes...)
is ill-formed (e.g. whenF
is not a callable type at all). C++14 changes that to a SFINAE (whenF
is not callable,std::result_of<F(Args...)>
simply doesn't have the type member).The motivation behind
std::result_of
is to determine the result of invoking a FunctionObject, in particular if that result type is different for different sets of arguments.
So to wrap it up: the error is caused by how the template type deduction is implemented in the c++11 version of this function. It simply works as expected with c++14, so it might be the best solution if this is a valid option for you.
I can confirm that it compiles and works with both recent versions of gcc and clang, given the -std=c++14
flag (but it failed with -std=c++11
).
EDIT: OP already uses C++14
The code actually uses std::result_of_t
which only appeared with C++14, so my remark above doesn't apply.
Also, the code would also actually work in C++11 using typename std::result_of<CALLABLE(ARGS&&...)>::type
instead of std::result_of_t<CALLABLE(ARGS&&...)>
(tested with clang).
So I'm not sure what's wrong. Maybe a bug in MSVC's implementation of the STL?
Upvotes: 1