Как удалить часть decltype (& MyClass :: funct), расширив следующие черты типа? - PullRequest
15 голосов
/ 13 мая 2019

Я хотел иметь черты типа, которые помогут мне получить тип класса из указателя на функцию-член. Я посмотрел на этот ответ и нашел свою половину пути к цели.

Это выглядит так:

#include <iostream>

// example class
struct MyClass {
    void funct() { std::cout << "funct has been called....\n"; }
};

// traits
template<typename Class> struct get_class{};
template<typename ReType, typename Class, typename... Args>
struct get_class<ReType(Class::*)(Args...)>
{
    using type = Class;
};
template<typename Type> using get_class_t = typename get_class<Type>::type;

int main()
{
    get_class_t<decltype(&MyClass::funct)> myObj;
    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---> this is a lot of typing
    myObj.funct();
    return 0;
}

Но, как показано в коде, мне нужно каждый раз писать get_class_t<decltype(&MyClass::funct)> или в случае

  auto ptr =  &MyClass::funct;
  get_class_t<decltype(ptr)> myObj;
  //         ^^^^^^^^^^^^^^

что много decltype() инг. Я хотел бы написать вместо

class_t<ptr> obj;
or
class_t<&MyClass::funct> myObj;

что удобнее.

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

template<typename Type>
auto helper_function(Type ptr)->get_class_t<Type>
{
    return get_class_t<Type>{};
}

template<typename Type>
using class_t = /* decltype(helper_function(Type ptr));*/ 
//             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // what could be here?

Я не знаю, как это сделать. Моя цель - расширить черты таким образом, чтобы я может создать объект как

auto ptr = &MyClass::funct;
class_t<ptr> myObj;
// or
class_t<&MyClass::funct> myObj;

Есть ли другой способ сделать это? или я должен придерживаться decltype() ING

Как я уже отметил, я хотел бы посмотреть, возможно ли это с C ++ 11?

Ответы [ 2 ]

11 голосов
/ 13 мая 2019

(Ответ заархивирован для будущих посетителей; для этого решения требуется C ++ 17!)


Вы действительно близки!

Хитрость auto аргументы шаблона и тот факт, что указатели на члены могут использоваться в качестве аргументов шаблона, например:

template <auto thing>
using class_t = get_class_t<decltype(thing)>;

int main()
{
    class_t<&MyClass::funct> myObj;
    myObj.funct();
}

Конечно, если вы можете написать это, вы уже знаете тип, так что вы быпросто напишите MyClass, так что это не очень полезно.

К сожалению, вы не сможете заставить его принять ptr в качестве аргумента шаблона;вы застряли с get_class_t для этого:

int main()
{
    auto ptr = &MyClass::funct;
    get_class_t<decltype(ptr)> myObj;
    myObj.funct();
}

( live demo )

В последнем случае хороший псевдоним типа может вам немного помочь:

auto ptr = &MyClass::funct;

using ClassType = get_class_t<decltype(ptr)>;
ClassType myObj;

myObj.funct();

( живая демонстрация )

Лично я считаю этот уровень многословия вполне разумным.

8 голосов
/ 13 мая 2019

Вы можете предоставить функцию, которая будет создавать необходимый объект. Это очень просто достичь:

template<typename T, typename ...Args>
auto makeObjectForMethod(T&&, Args&& ...args) -> get_class_t<decltype(&MyClass::funct)>
{
    using R = get_class_t<decltype(&MyClass::funct)>;
    return R{ std::forward(args)... };
}

int main()
{
    auto myObj = makeObjectForMethod(&MyClass::funct);

    myObj.funct();
    return 0;
}

Работает с C ++ 11 и довольно удобен: https://wandbox.org/permlink/usMa3fA0I2HCNJ7M

Единственный недостаток, что в случае полей класса это не очень полезно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...