в std :: result_of нет типа с именем type; получить тип возвращаемого значения из функций перегрузки

Я изучаю, как получить type возвращаемого значения перегруженной функции test() vs test(double).

Я изменил код из SO-ответа (от Криса).

#include <type_traits>
#include <utility>

int test();
double test(double x);

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

int main() {
    std::result_of< TestType<double> >::type n = 0;
     //^ ### compile error ###
    using doubleDat = std::result_of< TestType<double> >::type ;
    doubleDat n=0;
}

У меня ошибка компиляции.

ошибка: нет типа с именем 'type' в 'std :: result_of'

Насколько я понимаю: -

  • TestType<...> - это «вариативный шаблон».
    По моим собственным словам, он действует как сжатое сокращение с любым количеством параметров.

  • TestType<double> - это идентификатор функции test(double).

  • std::result_of<TestType<double>>::type - тип возвращаемого значения test(double).
    doubleDat должен быть double.

Вопрос: Почему не компилируется? Как это решить?

Я читал это:

Подсказка: после долгих поисков я чувствую слабый запах того, что мой код подвергается "самому неприятному синтаксическому анализу".


person javaLover    schedule 16.02.2017    source источник


Ответы (1)


Посмотрите, до чего расширяется ваш TestType<double>:

test(std::declval<double>())(double)

test(std::decvlal<double>) равно double, поэтому вы получите double(double)

result_of<double(double)>::type спрашивает, можно ли вызвать double с аргументом типа double.

Ответ отрицательный, потому что double не вызывается, поэтому нет вложенного типа.

Вам необходимо прочитать документацию для result_of, чтобы понять, как его использовать. Тип result_of<F(Arg)>::type является результатом вызова F с аргументом Arg. Если F вызывается с аргументом Arg, вы получаете возвращаемый тип, если он не вызывается с аргументом Arg, тогда вложенный type не существует.

Итак, это сработает:

using func_type = TestType<double>;
using doubleDat = std::result_of<func_type*(double)>::type;

Это создает псевдоним для функции типа TestType<double> (т.е. double(double)), а затем спрашивает, можете ли вы вызвать указатель на этот тип (например, double(*)(double)) с аргументом типа double. И вы можете, так что вы type действительны.

person Jonathan Wakely    schedule 16.02.2017
comment
Собирался написать свой ответ после экспериментов. Ты подтолкнул меня на это. - person Sebastian Redl; 16.02.2017
comment
Я хочу хорошо разбираться в этих вещах. (Я учусь медленно, методом проб и ошибок.) Как получить обширные знания в этой области одним большим куском? Есть ли какая-нибудь книга, например какой из ссылки SO на книгу C ++, подробно освещающей эти темы ? обучающее видео? Вы пишете книги по C ++? - person javaLover; 16.02.2017
comment
Благодарить. Думаю, теперь мне нужно носить доспехи. - person javaLover; 16.02.2017