Почему функция decltype не работает с перегруженными функциями?

decltype терпит неудачу, если функция, с которой вы звоните, перегружена, как в этом коде:

#include <iostream>

int test(double x, double y);
double test(int x, int y);
char test(char x, int y);

int main()
{
  std::cout << decltype(test) << std::endl;

  return 0;
}

Результаты:

error: decltype cannot resolve address of overloaded function

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

std::cout << decltype(test(double, double)) << std::endl;

или это:

double x = 5, y = 2;
std::cout << decltype(test(x, y)) << std::endl;

Поскольку функция не может быть перегружена просто на основе типа возврата, не будет передаваться ни тип данных, ни фактические переменные в вызов decltype, чтобы рассказать, какую из перегрузок он должен исследовать? Что мне здесь не хватает?

Ответ 1

Чтобы определить тип функции из типа аргументов, которые вы передадите, вы можете "построить" тип возврата с помощью decltype и "вызвать" его с этими типами, а затем добавить параметр чтобы собрать весь тип вместе.

template<typename... Ts>
using TestType = decltype(test(std::declval<Ts>()...))(Ts...);

Выполнение TestType<double, double> приведет к типу int(double, double). Вы можете найти полный пример здесь.

В качестве альтернативы синтаксис типа возвращаемого типа может выглядеть следующим образом:

template<typename... Ts>
using TestType = auto(Ts...) -> decltype(test(std::declval<Ts>()...));

Ответ 2

Я верю, что вы можете искать std::result_of<>

cppreference страница.