在下面的代码中,单独编译每个模板函数不会导致错误,但是当它们放在一起时会发生编译错误。谁能告诉我为什么,以及如何解决它?
#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;
}
编译器是VC2015,错误消息是:
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}'
附加信息,如果我不使用方法重载,即对模板函数使用不同的名称,编译器报告没有错误。
答案 0 :(得分:1)
在模板可变参数函数上使用std::result_of
的方式在c ++ 14中有效,但在c ++ 11中则无效。
在此处引用文档(source):
正如C ++ 11中所阐述的那样,
std::result_of
在F(ArgTypes...)
格式错误时无法编译(例如,当F
根本不是可调用类型时)。 C ++ 14将其更改为SFINAE(F
无法调用时,std::result_of<F(Args...)>
根本没有类型成员)。
std::result_of
背后的动机是确定调用FunctionObject的结果,特别是如果该结果类型对于不同的参数集是不同的。
所以要把它包装起来:错误是由在这个函数的c ++ 11版本中如何实现模板类型推导引起的。它只是按照预期的c ++ 14工作,所以如果这是一个有效的选项,它可能是最好的解决方案。
我可以确认它编译并使用最新版本的gcc和clang,给定-std=c++14
标志(但它失败了-std=c++11
)。
编辑:OP已经使用C ++ 14
代码实际上使用的std::result_of_t
只出现在C ++ 14中,所以我上面的评论并不适用。
此外,代码实际上也可以在C ++ 11中使用typename std::result_of<CALLABLE(ARGS&&...)>::type
而不是std::result_of_t<CALLABLE(ARGS&&...)>
(使用clang测试)。
所以我不确定是什么错。也许是MSVC实施STL的一个错误?