2015-08-20 3 views
3

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

class AA 
{ 
public: 
    AA(){}; 
    ~AA(){}; 
    std::string type="AA"; 
}; 

class BB 
{ 
public: 
    BB(){}; 
    ~BB(){}; 
    template <typename T, typename TT> 
    void test(T& a, TT(T::*memberPtr)) 
    { 
     std::cout<<"test: "<<(a.*memberPtr)<<std::endl; 
    } 
    std::string type="BB"; 
}; 

int main() 
{ 
    AA a; 
    BB b; 
    b.test(a, &AA::type); 
} 

Но я знаю, что все, что во время компиляции, так что я интересно, если это возможно, чтобы написать что-то эквивалентное, но только с шаблонами? Так что я мог бы написать что-то вроде:

b.test<&AA::type>(a); 

, который вызывает в тесте (а):

std::cout<<"test: "<< (a.*MEMBER) <<std::endl; // MEMBER is given in template 

или что-то в этом роде.

+0

Вы можете передать указатель на метод геттера вместо переменной-члена. –

+0

Переменная 'memberPtr' в вашей функции' test' уже делает то, что вы хотите - указатели на функции-члены - это значения времени выполнения. – Griwes

+0

Я понимаю, что я, возможно, неправильно понял, что мой указатель memberPtr действительно ... это определяется во время компиляции или во время выполнения? Есть ли какая-либо стоимость для использования (a. * MEMBER) по сравнению с просто ссылкой «a.type»? – StormRider

ответ

4

Вы не можете сделать только test<&AA::type>, так как вам нужно также сообщить шаблону функции, что типа указателя на член, которого вы ожидаете. Типичная картина:

template <class M, M member, class T> // deduced go last 
void test(T& a) { 
    cout << (a.*member); 
} 

С использованием:

test<decltype(&AA::type), &AA::type> 

Я считаю, что в настоящее время предложение о сокращении подробности, но до тех пор, это не самое худшее в мире, и вы могли бы всегда:

#define TYPE_AND_VAL(foo) decltype(foo), foo 
test<TYPE_AND_VAL(&AA::type)> 
+0

Спасибо за ваш ответ, он ближе к тому, что я хочу, но мне интересно: вы все еще используете указатель, поэтому я думаю, что он определяется во время выполнения? (Я действительно не знаю указателей на функции) Поскольку я точно знаю, какой член я укажу на время компиляции, я догадался, что во время компиляции можно определить все. – StormRider

+0

@ user52730 Это * * во время компиляции. Аргументы шаблона должны быть известны во время компиляции. – Barry

+0

Хорошо, и можете ли вы подтвердить, что мой код имел дело с указателем во время выполнения? Указатели функций по-прежнему довольно мрачны для меня. – StormRider

0

Просто устраните это несколько сильно типизированное. Вместо того, чтобы просить пользователя предоставить вам класс и членский указатель, просто примите шаблонный функтор и вызовите его operator(). Это будет наиболее гибким и наименее подробным.

+0

Это не ответит на вопрос, но вы, вероятно, правы, я исследую эту возможность, спасибо! – StormRider

1

Это связано с ответом Сергея, но компромисс должен был пройти ваш класс и лямбда. Компилятор может to inline the lambda так что вы, вероятно, не платить за это время выполнения:

struct BB 
{ 
public: 
    template <typename T, typename F> 
    void test(T& a, F f) 
    { 
     std::cout<<"test: "<< f(a) <<std::endl; 
    } 
    std::string type="BB"; 
}; 

int main() 
{ 
    AA a; 
    BB b; 
    b.test(a, [](AA& a){return a.type;}); 
} 

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

+0

Это интересно спасибо!Однако я ищу что-то более читаемое, чем лямбда. – StormRider

+0

@ user52730 Лично я считаю, что лямбда более читабельна, чем синтаксис функции-указатель-член, но нормально. Вы можете использовать 'auto' с lambdas, если хотите дать ему имя. –

Смежные вопросы