Почему 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 типы данных или фактические переменные, чтобы сообщить ей, какую из перегрузок она должна проверять? Что мне здесь не хватает?


person cf stands with Monica    schedule 10.03.2014    source источник
comment
Я не уверен, чего вы пытаетесь достичь, выводя тип, но ваш последний фрагмент кода работает отдельно от этого.   -  person chris    schedule 10.03.2014
comment
@chris Это немного тестового кода. Бит реального кода, использующий decltype, не удался, когда я дал ему перегруженные функции, и я пытался точно определить проблему.   -  person cf stands with Monica    schedule 10.03.2014
comment
Вы пытаетесь найти тип возвращаемого значения или тип фактической функции?   -  person chris    schedule 10.03.2014
comment
@chris Я почти уверен, что код получает тип функции. Сам код на самом деле находится в библиотеке шаблонов, которая выше моего уровня навыков, но, похоже, он получает тип функции шаблона.   -  person cf stands with Monica    schedule 10.03.2014
comment
Поправьте меня, если я ошибаюсь, но я, кажется, помню, что decltype обычно используется вместе с declval таким образом, что declval параметры передаются в функцию для возврата типа.   -  person rwong    schedule 10.03.2014
comment
@rwong declval не используется в этом сегменте кода. Изучив библиотеку подробнее, я думаю, что она пытается использовать возвращаемый тип функции для создания соответствующей функции того же типа.   -  person cf stands with Monica    schedule 10.03.2014


Ответы (3)


Чтобы определить тип функции из типа аргументов, которые вы передадите, вы можете «создать» возвращаемый тип, используя 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>()...));
person chris    schedule 10.03.2014
comment
Есть ли альтернатива этому, которая будет построена на VS 2013? Пример кода выдает такие ошибки, как error C2061: syntax error : identifier 'Ts', error C3203: 'TestType' : unspecialized alias template can't be used as a template argument for template parameter '_Ty1', expected a real type. - person LogicStuff; 08.07.2015
comment
На данный момент у меня нет 2013 года (он работает с веб-компилятором, который, я думаю, 2015 года). Что-то, что вы можете попробовать, это использовать шаблонную структуру с type typedef. template<typename... Ts> struct TestType {typedef ... type;};, с использованием TestType<int, int>::type - person chris; 08.07.2015

Я полагаю, вы ищете std::result_of<>

cppreference.

person en4bz    schedule 10.03.2014
comment
Чтобы использовать result_of, вам нужен тип. И проблема в том, что у вас нет типа, потому что нет одного типа. - person Barry; 01.03.2017

Я нашел другой способ: использовать std::declval для создания поддельного объекта, затем использовать decltype:

#include <type_traits>
#include <functional>
int myfunc(int a)
{
    return a;
}
float myfunc(float a)
{
    return a;
}

int main()
{
    decltype(myfunc(std::declval<float>())) a;  // return type
    std::function<decltype(a)(float)> fun;      // function type
    return 0;
}
person 陈浩南    schedule 29.07.2020