c ++编译错误涉及方法重载的2个模板函数

时间:2016-04-08 03:36:12

标签: c++ templates

在下面的代码中,单独编译每个模板函数不会导致错误,但是当它们放在一起时会发生编译错误。谁能告诉我为什么,以及如何解决它?

#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}'

附加信息,如果我不使用方法重载,即对模板函数使用不同的名称,编译器报告没有错误。

1 个答案:

答案 0 :(得分:1)

在模板可变参数函数上使用std::result_of的方式在c ++ 14中有效,但在c ++ 11中则无效。

在此处引用文档(source):

  

正如C ++ 11中所阐述的那样,std::result_ofF(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的一个错误?