Как я могу найти тип возврата функции шаблона - PullRequest
0 голосов
/ 02 апреля 2019

Мне нужно найти тип результата функции шаблона для чего-то вроде этого:

template<typename T>
T fun1(
T arg1,
result_fun<T>(some_fun)
);

Или как-то так.Поэтому в стандартной библиотеке я нахожу result_of (я тоже нахожу invoke_result, он тоже не работает).Поэтому я нахожу сообщение , где я нахожу синтаксис этой функции.Он работает на sipmle код , но ... Он не работает с указателями ... пример (он и код идеона равно):

#include <iostream>
#include <type_traits>

using namespace std;

template <typename T>
T *some(T x){
    return &x;
}

template<typename T>
void somestrange(T x, typename result_of<decltype(&some<decltype(x)>)(decltype(x))>::type z);

template<typename T>
void somestrange(T x, typename result_of<decltype(&some<decltype(x)>)(decltype(x))>::type z){
    cout << is_same<decltype(x), int>() << endl
     << is_same<decltype(z), int *>();
}

int main(){
    int x = 0;
    int *z = nullptr;
    somestrange(x, z);
    return 0;
}

Этобудет работать, но если шаблон получит указатель ...

#include <iostream>
#include <type_traits>

using namespace std;

template <typename T>
T **some(T *x){
    return &x;
}

template<typename T>
void somestrange(T x, typename result_of<decltype(&some<decltype(x)>)(decltype(x))>::type z);

template<typename T>
void somestrange(T x, typename result_of<decltype(&some<decltype(x)>)(decltype(x))>::type z){
    cout << is_same<decltype(x), int>() << endl
     << is_same<decltype(z), int *>();
}

int main(){
    int *x = 0;
    int **z = nullptr;
    somestrange(x, z);
    return 0;
}

Компиляция будет злой.Поэтому я думаю, что я могу сделать.И я создаю собственный weel ... Итак, я пишу что-то вроде this :

#include <iostream>
#include <type_traits>
#include <utility>
#include <typeinfo>

using namespace std;

template<typename Fun, typename Arg>
inline auto myinvoke(Fun&& f, Arg&& arg)
    -> decltype(forward<Fun>(f)(forward<Arg>(arg)))
{
    return (forward<Fun>(f)(forward<Arg>(arg)));
}

template<typename Fun, typename Arg>
struct return_type {
    using type = decltype(myinvoke(declval<Fun>(), declval<Arg>()));
};

template<typename Fun, typename Arg>
using return_type_t = typename return_type<Fun, Arg>::type;


template <typename T>
T *some(T x){
    return &x;
}

template<typename T>
void somestrange(T x, return_type_t<decltype(some<T>), T> z);

template<typename T>
void somestrange(T x, return_type_t<decltype(some<T>), T> z){
    cout << is_same<decltype(x), int>() << endl
     << is_same<decltype(z), int *>();
}

int main(){
    int x = 0;
    int *z = nullptr;
    somestrange(x, z);
    return 0;
}

Но если я здесь, вы можете догадаться, что это не сработает.И вы будете правы, потому что это не работает с ptr , то же самое, что не может работать result_of:

#include <iostream>
#include <type_traits>
#include <utility>
#include <typeinfo>

using namespace std;

template<typename Fun, typename Arg>
inline auto myinvoke(Fun && f, Arg&& arg)
    -> decltype(forward<Fun>(f)(forward<Arg>(arg)))
{
    return (forward<Fun>(f)(forward<Arg>(arg)));
}

template<typename Fun, typename Arg>
struct return_type {
    using type = decltype(myinvoke(declval<Fun>(), declval<Arg>()));
};

template<typename Fun, typename Arg>
using return_type_t = typename return_type<Fun, Arg>::type;


template <typename T>
T **some(T *x){
    return &x;
}

template<typename T>
void somestrange(T x, return_type_t<decltype(some<T>), T> z);

template<typename T>
void somestrange(T x, return_type_t<decltype(some<T>), T> z){
    cout << is_same<decltype(x), int>() << endl
     << is_same<decltype(z), int *>();
}

int main(){
    int *x = 0;
    int **z = nullptr;
    somestrange(x, z);
    return 0;
}

Так что я могу с этим сделать?Кто-нибудь знает, как я могу решить эту проблему (я могу использовать только STL)?Спасибо за ответ

1 Ответ

2 голосов
/ 02 апреля 2019

С

int *x = 0;
int **z = nullptr;
somestrange(x, z);

и

template<typename T>
void somestrange(T x, return_type_t<decltype(some<T>), T> z);
  • T будет int*
  • some<T> ожидает T* аргумент

Так что измените на

template<typename T>
void somestrange(T* x, return_type_t<decltype(some<T>), T*> z);

или

template<typename T>
void somestrange(T* x, return_type_t<decltype(some<std::remove_pointer_t<T>>), T> z);

Демо

Или не указывайте явно шаблон и разрешите вычет:

template<typename T>
void somestrange(T x, decltype(some(std::declval<T>())) z);

Демо

...