为什么以下程序没有选择与第一个模板参数相同类型的参数?

时间:2019-04-20 16:30:48

标签: c++ templates c++14 variadic-templates sfinae

我正在尝试编写一个函数,使得f<T>(args..)返回类型为T的第一个参数。

以下程序似乎总是选择第一个专业化版本,因此打印97(ASCII代码为'a')。尽管第二个不需要将char转换为int。有人可以解释一下这种行为吗?

我是SFINAE和元编程的新手。

  #include <iostream>
  using namespace std;

  template <typename T, typename ...Ts>
  T f(T a, Ts... args) {
    return a;
  }

  template <typename R, typename T, typename ...Ts>
  R f(typename enable_if<!is_same<R, T>::value, T>::type a, Ts... args) {
    return f<R>(args...);
  }

  int main() {
    cout << f<int>('a', 12);
  }

2 个答案:

答案 0 :(得分:7)

std::enable_if的第二个模板参数应该是R,这是您希望拥有的。

以下应该有效

 template < typename R, typename T, typename ...Ts>
 typename enable_if<!is_same<R, T>::value, R>::type f(T const& t, Ts&&... args) 
 //                                       ^^^         ^^^^^^^^^^^
 {
       return f<R>(std::forward<Ts>(args)...); // forward the args further
 }

答案 1 :(得分:4)

您的代码的第一个功能参数在非推论上下文中。 enable_if< expr, T >::type 无法推论T。这是在“非推论上下文”中。

由于无法推论Tfoo<int>( 7 )无法使用该重载;编译器不知道T是什么。 foo<int,int>(7)会称呼它。

  template <typename R, typename T, typename ...Ts>
  typename enable_if<!is_same<R, T>::value, R>::type f(T a, Ts... args) 

现在T处于推论上下文中。我们并没有试图推论R(我们也不能从返回类型推论得出)。