Why does the following program not select the argu

2019-06-20 01:21发布

问题:

I am trying to write a function such that f<T>(args..) returns the first parameter of type T.

The following program seems to always select the first specialization thus printing 97 (ASCII code of 'a'). Though the second one wouldn't require converting char to int. Could someone please explain the behavior?

I am new to SFINAE and meta-programming.

  #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);
  }

回答1:

Your code's first function parameter is in a non-deduced context. enable_if< expr, T >::type cannot deduce T. It is in a "non-deduced context".

Being unable to deduce T, foo<int>( 7 ) cannot use that overload; the compiler does not know what T is. foo<int,int>(7) would call it.

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

now T is in a deduced context. We aren't trying to deduce R (nor can we deduce from a return type).



回答2:

The second template argument of the std::enable_if should be the R, which is what you desire to have.

Following should work

 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
 }