Почему следующая программа не выбирает аргумент того же типа, что и первый параметр шаблона? - PullRequest
6 голосов
/ 20 апреля 2019

Я пытаюсь написать такую ​​функцию, чтобы 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 ]

7 голосов
/ 20 апреля 2019

Второй аргумент шаблона 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
 }
4 голосов
/ 20 апреля 2019

Первый функциональный параметр вашего кода находится в не выводимом контексте. enable_if< expr, T >::type не может выводить T. Он находится в «не выводимом контексте».

Будучи неспособным вывести T, foo<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 (и мы не можем вывести из возвращаемого типа).

...