Единый шаблонный вывод для нескольких аргументов - PullRequest
1 голос
/ 05 июня 2019

Я хотел бы посмотреть, возможно ли (хотя у меня такое ощущение, что это не так), возможно ли применять унифицированные типы на основе первого заданного аргумента шаблона.Например:

template <class T>
void foo(T, T) {}

int main() {
  // deduced as int
  foo(1, 1);

  // deduced as double
  foo(1.0, 1.0);

  // not deducible, will error.
  //foo(1.0, 1);

  return 0;
}

Существует ли какая-либо техника, которая позволит мне заставить второй параметр foo быть точно первым?Я действительно понимаю, что каноническое решение, хотя и немного более многословное, будет foo<double>(1.0, 1).

При этом я хотел бы иметь возможность выполнить foo(1.0, 1), что заставит второй тип параметра стать первым,и upcast от 1 до 1.0.

Кроме того, foo(1, 1.0) не будет выполнен, потому что первый параметр устанавливает foo в foo<int>, и поэтому второй параметр не может быть понижен до int.

Наконец, я хотел бы иметь возможность делать это без рекурсивных шаблонов, так как я хотел бы применить эту технику к конструкторам объектов.

1 Ответ

3 голосов
/ 05 июня 2019

Просто используйте параметр шаблона в параметрах функции после первого в «недуводимых контекстах»:

template <typename T>
struct type_identity {
    using type = T;
};
template <typename T>
using type_identity_t = typename type_identity<T>::type;

template <class T>
void foo(T, type_identity_t<T>) {}

Теперь foo(1.0, 1) означает то же самое, что и foo<double>(1.0, 1), а специализация функции имеет аргументы (double, double), поэтому 1 неявно преобразуется из int в double. И наоборот, foo(1, 1.0) означает foo<int>(1, 1.0), а 1.0 неявно преобразуется в int.

(Примечание std::type_identity_t выходит на C ++ 20 .)

...