Использование типа члена класса первого типа в шаблоне - PullRequest
1 голос
/ 24 марта 2020

При поиске на сайте я нашел этот ответ для получения типа члена внутри класса. Исходя из этого, я сделал следующий пример, который успешно компилируется.

#include <iostream>
#include <stdio.h>
#include <string>

using namespace std;


class sig_class_t{
public:
    int field;
};

class usig_class_t{
public:
    unsigned int field;
};

template <class T, class M> M get_member_type(M T:: *);

template<typename my_class = sig_class_t, typename my_type = decltype(get_member_type(&my_class::field))>
class Tricky{
    my_type it;
public:
    my_type get_it();
    void set_it(my_type value);
};

template<typename my_class, typename my_type>
my_type Tricky<my_class,my_type>::get_it(){
    return it;
}

template<typename my_class, typename my_type>
void Tricky<my_class,my_type>::set_it(my_type value){
    it = value;
}

int main(int argc, char *argv[])
{
    return 0;
}

Как get_member_type может определить тип данного указателя?
Этот код кажется довольно сложным, и мне было бы неудобно использовать его, если я не понимаю, как оно работает.

Ответы [ 2 ]

2 голосов
/ 24 марта 2020

С

template<typename my_class = sig_class_t, 
         typename my_type = decltype(get_member_type(&my_class::field))>
class Tricky{
    my_type it;
public:
    my_type get_it();
    void set_it(my_type value);
};

Вы передаете &my_class::field на get_member_type. &my_class::field - это указатель на field член myclass, поэтому он имеет тип

decltype(my_class::field) myclass::*

или, чтобы вставить в него engli sh, myclass указатель на тип элемента field участник. По умолчанию (поскольку он использует sig_class_t), то есть

int sig_class_t::*

Почему вы передаете это

template <class T, class M> M get_member_type(M T:: *);

M выводится как int и T выводится до sig_class_t. Затем функция «возвращает» объект типа M, поэтому decltype(get_member_type(&my_class::field)) разрешается в M (int в случае по умолчанию), и именно так my_type выводится как тип, на который указывает указатель .

1 голос
/ 24 марта 2020

Хотя это не прямой ответ на ваш вопрос, мне легче понять это выражение:

decltype(std::declval<my_class>().field)

Часть std::declval<my_class>() возвращает "фиктивный" my_class объект, поэтому мы можем использовать .field на нем. И это подвыражение заключено в decltype, что даст тип field.

(Обратите внимание, что declval можно использовать только в неоцененном контексте. Параметр decltype таков контекст.)

...