simon
simon

Reputation: 391

c++ compiling error involve 2 template functions of method overloading

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

Answers (1)

giant_teapot
giant_teapot

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 when F(ArgTypes...) is ill-formed (e.g. when F is not a callable type at all). C++14 changes that to a SFINAE (when F 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

Related Questions