C ++ 11: std :: result_of <> аргумент шаблона vs std :: function <> - PullRequest
0 голосов
/ 13 июня 2018

Я провел некоторое исследование по std::result_of<> и знаю, как оно используется на высоком уровне, но все еще довольно запутался в этой магической вещи.

Так что, если я правильно понимаю, формаR (Args..) должен интерпретироваться компилятором как тип функции, принимающий аргументы типов Args... и возвращающий тип R, и использование очень оправдано при указании std::function<int(int)>, который объявляет тип функции, принимающий intв качестве единственного аргумента и возвращая int.

Однако значение вышесказанного внезапно меняется, когда используется то же понятие в контексте std::result_of<F(Args...)> (обратите внимание, что я изменил R на F и удалил (пробел) между F и (, чтобы обозначить разницу - согласно cppreference значение F(Args...) становится выражением INVOKE времени компиляции - я имею в виду, я вроде понимаючто основная цель std::result_of<F(Args...)> состоит в том, чтобы использовать понятие INVOKE, чтобы выбрать правильную перегрузку (если имеется более одной перегрузки), и, конечно, вывести значение возвратаpe такого вызова (во время разрешения времени компиляции) - фактически, это было бы примерно так: decltype(std::declval<F>()(std::declval<Args>()...)) - однако понятие F (Args...) - по сравнению с std::function<R (Args...)> - было бы интерпретировано компилятором какТип функции принимает Args... и возвращает тип F, где теперь F - это тип функции, который мы пытаемся получить тип возвращаемого значения!

Конечно, с помощью decltypeи std::declval, реализация std::result_of кажется разумной, но я читал, что boost как-то реализовал result_of в C ++ 98/03, где decltype и std::declval не существовало - мне интересно, как бы этовозможно (возможно, с некоторыми очень хитрыми приемами)?

Итак, еще раз: понятие R (Args...) в контексте аргумента шаблона всегда интерпретируется / выводитсякак тип функции с типом возвращаемого значения R, независимо от того, является ли включающий шаблон std::function<> или std::result_of<>?в то время как std::result_of<> каким-то образом интерпретирует «тип возвращаемого значения» F и «возвращает» фактический тип возвращаемого значения, определенный std::result_of<F(Args...)>::type?Или std::result_of<F(Args...)> просто интерпретирует F(Args...) по-разному, поэтому он знает, что это волшебное INVOKE выражение?

Спасибо за ваше предстоящее разъяснение!

Ответы [ 2 ]

0 голосов
/ 13 июня 2018

Чтобы реализовать его без decltype - ну, простая реализация старой школы, которая охватывает несколько основных случаев, вероятно, будет выглядеть примерно так:

template<class F> struct MemberRetVal;
template<class C,typename R> struct MemberRetVal<R (C::*)()> {
    using type = R;
};
template<class C,typename R> struct MemberRetVal<R (C::*)() const> {
    using type = R;
};
template<class C,typename R, typename A1> struct MemberRetVal<R (C::*)(A1)> {
    using type = R;
};
template<class C,typename R, typename A1> struct MemberRetVal<R (C::*)(A1) const> {
    using type = R;
};
// ...
// A few more member function arities
// ...

template<typename F> struct ResultOf;
template<typename F> struct ResultOf<F (*)()> {
    using type = typename MemberRetVal<&F::operator()>::type;
};
template<typename R> struct ResultOf<(R (*)())(*)()> {
    using type = R;
};
template<typename F, typename A1> struct ResultOf<F (*)(A1)> {
    using type = typename MemberRetVal<&F::operator()>::type;
};
template<typename R, typename A1> struct ResultOf<(R (*)(A1))(*)(A1)> {
    using type = R;
};
// and so forth

Для случая operator() требуется несколько более сложная диспетчеризация, нов противном случае - это приблизительный путь.

0 голосов
/ 13 июня 2018

Z(A,B,C) это просто тип.Это тип функции.

Вы можете передавать типы в шаблоны.То, что шаблон делает с типом, зависит от шаблона.

std::function<X> ожидает тип функции.Он преобразует его в сигнатуру operator().

std::result_of<X> ожидает тип функции.Если задано A(Ts...), вычисляется результат использования () для вызова объекта типа A с аргументами Ts....

Он был помечен как ограниченный в потому что типы функций иногда делают забавные вещи (аргументы распада, strip const и т. Д.).Теперь есть invoke_result<F, Ts...>, который ведет себя почти так же, как result_of<F(Ts...)>, с небольшими различиями в угловых случаях.

Результатом всегда было злоупотребление синтаксисом типа функции.Но здесь нет глубокой магии;шаблоны делают все, что хотят, с переданными типами.

В вы можете получить ограниченную функциональность типа "result_of", сопоставляя типы указателей с функциями сопоставления с образцом и проверяя &T::operator().Невозможно получить все необходимые возможности в без decltype / declval, расширений компилятора или заголовков TR pre- .

...