Указатель на члена класса в качестве параметра шаблона

Я хочу использовать указатель на член класса в качестве параметра шаблона, как в:

template <class Class, class Result, Result Class::*Member>
struct MyStruct {
// ...
};

Используя эту структуру, как MyStruct<SomeClass, SomeResult, &SomeClass::value> variable работает просто отлично, но мне это не нравится, я должен указать SomeClass а также SomeResult,

Я хотел бы использовать MyStruct<&SomeClass::value> variable если это возможно, но без потери возможности пройти любой класс и иметь любой тип результата.

Я попробовал следующее, но синтаксис недопустим:

template <class Class, class Result>
template <Result Class::*Member>
struct MyStruct {
// ...
};

ошибка: слишком много списков параметров шаблона

Я попытался использовать вспомогательную функцию (которая на самом деле работает в Clang, но GCC отказывается):

template <class Class, class Result>
static constexpr auto makeMyStruct(Result Class::*member) ->
MyStruct<Class, Result, member> {
// ...
}

ошибка: использование параметра «член» вне тела функции
ошибка: аргумент шаблона 3 неверен

Можно ли иметь простой MyStruct<&SomeClass::value>и если да, то как?

Связанный вопрос, который не решил мой вопрос:

19

Решение

Это может быть решением в C ++ 11:

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

template<class T>
struct remove_member_pointer {
typedef T type;
};

template<class Parent, class T>
struct remove_member_pointer<T Parent::*> {
typedef T type;
};

template<class T>
struct baseof_member_pointer {
typedef T type;
};

template<class Parent, class T>
struct baseof_member_pointer<T Parent::*> {
typedef Parent type;
};

Теперь вы можете определить дополнительный 4-строчный макрос-обертку для каждой структуры:

template<class Class, class Result, Result Class::*Member>
struct _MyStruct {
// ...
};

#define MyStruct(MemberPtr) \
_MyStruct<baseof_member_pointer<decltype(MemberPtr)>::type, \
remove_member_pointer<decltype(MemberPtr)>::type, \
MemberPtr>

… и используйте его следующим образом:

MyStruct(&SomeClass::value)  myStruct; // <-- object of type MyStruct<&SomeClass:value>

Я использую это как промежуточное решение, пока мы не переключимся на C ++ 17.

4

Другие решения

Ответ на мой вопрос был предложен в этой статье для следующего стандарта C ++:

Этот синтаксис был предложен:

template<using typename T, T t>
struct some_struct { /* ... */ };

some_struct<&A::f> x;

Необходимость в новой синтаксической конструкции означает, что вы не можете сделать это сейчас.

Я надеюсь, что n3601 будет принят. 🙂

11

В с ++ 17 с добавлением auto в аргументах шаблона (P0127), Я думаю, что теперь вы можете сделать:

template<auto value>
struct MyStruct {};

template<typename Class, typename Result, Result Class::* value>
struct MyStruct<value> {
// add members using Class, Result, and value here
using containing_type = Class;
};

typename MyStruct<&Something::theotherthing>::containing_type x = Something();
7

Сделайте ваш класс результатов дочерним по отношению к вашему классу шаблонов. предполагая, что член-указатель является объектом вашего класса результатов публично или как угодно, вы можете получить доступ к любым объектам, выполнив что-то вроде этого

template <stuff for this class> :: public result
{
blah
}
-6
По вопросам рекламы [email protected]