Могу ли я получить тип возврата функции из подписи? - PullRequest
0 голосов
/ 04 марта 2019

Итак, у меня есть тонна функций, подобных этим:

template <typename T>
bool Zero(const T, const T, const T);
template <typename T>
T One(const T, const T, const T, bool);
template <typename T>
T Three(const T, const T, const T, const T, const T, const T);

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

template <typename T>
decltype(Zero<decltype(declval<T>().x)>(decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()))) ZeroWrapper(const T);
template <typename T>
decltype(One<decltype(declval<T>().x)>(decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()), bool())) OneWrapper(const T);
template <typename T>
decltype(Three<decltype(declval<T>().x)>(decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()))) ThreeWrapper(const T);

Как видите, все эти decltype(declval<T>().x) ужасно трудно читать.Могу ли я шаблон using или есть какая-то стандартная функция, которая позволит мне извлечь тип возвращаемого значения из указателя функции без передачи типов аргумента decltype или result_of?Так что-то вроде этого:

template <typename T>
foo_t<Zero<decltype(declval<T>().x)>> ZeroWrapper(const T);
template <typename T>
foo_t<One<decltype(declval<T>().x)>> OneWrapper(const T);
template <typename T>
foo_t<Three<decltype(declval<T>().x)>> ThreeWrapper(const T);

Ответы [ 2 ]

0 голосов
/ 04 марта 2019

In объект function наделен Руководством по дедукции , которое позволяет ему определять свой тип по аргументу, переданному вконструкторТак, например, учитывая функцию int foo() в , мы должны были сделать:

function<int()> bar(foo);

In bar 'Тип s function<int()> будет получен, если мы просто:

function bar(foo);

Таким образом, мы можем использовать Руководство по дедукции для заполнения временной function только только подписью;таким образом, используя function result_type, чтобы найти результат ваших функций помощника:

template <typename T>
typename decltype(function(Zero<decltype(declval<T>().x)>))::return_type ZeroWrapper(const T);
template <typename T>
typename decltype(function(One<decltype(declval<T>().x)>))::return_type OneWrapper(const T);
template <typename T>
typename decltype(function(Three<decltype(declval<T>().x)>))::return_type ThreeWrapper(const T);

Live Example

0 голосов
/ 04 марта 2019

Могу ли я шаблонизировать использование или есть какая-то стандартная функция, которая позволит мне извлечь тип возвращаемого значения из указателя функции, не передавая типы аргументов decltype или result_of?

Да!

#include <tuple>
#include <functional>

template<class T>
struct callable_trait
{};

template<class R, class... Args>
struct callable_trait<std::function<R(Args...)>>
{
    using return_type    = R;
    using argument_types = std::tuple<Args...>;
};

template<auto callable>
using return_type = typename callable_trait<decltype(std::function{callable})>::return_type;

return_type<some_callable> - это тип, возвращаемый some_callable при вызове с соответствующими аргументами.При этом используется std::function, чтобы обеспечить специализацию для каждого возможного вида вызываемого объекта (свободная функция, указатель функции, функция-член, объект функтора).Это объяснено в этом ответе StackOverflow .


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

template <typename T>
bool Zero(const T, const T, const T);
template <typename T>
T One(const T, const T, const T, bool);
template <typename T>
T Three(const T, const T, const T, const T, const T, const T);

template <typename T>
return_type<Zero<T>>  ZeroWrapper(const T);
template <typename T>
return_type<One<T>>   OneWrapper(const T);
template <typename T>
return_type<Three<T>> ThreeWrapper(const T);

Полная демонстрация

...