Указатель на член класса в качестве параметра шаблона
Я хочу использовать указатель на член класса в качестве параметра шаблона, как в:
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> {
// ...
}
Ошибка: использование параметра 'member' вне тела функции
ошибка: аргумент шаблона 3 недопустим
Возможно ли иметь простой MyStruct<&SomeClass::value>
, и если да, то как?
Связанный вопрос, который не решил мой вопрос:
4 ответа:
Это может быть решением в C++11:
Можно определить следующие признаки универсального типа:
Теперь вы можете определить дополнительный 4-строчный макрос-оболочку для каждой структуры: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; };
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>
... и используйте его следующим образом:
Я использую это как промежуточное решение, пока мы не перейдем на C++17.MyStruct(&SomeClass::value) myStruct; // <-- object of type MyStruct<&SomeClass:value>
Ответ на мой вопрос был предложен в этой статье для следующего предстоящего стандарта C++:
Был предложен следующий синтаксис:
template<using typename T, T t> struct some_struct { /* ... */ }; some_struct<&A::f> x;
Необходимость в новой синтаксической конструкции указывает на то, что вы не можете сделать это сейчас.
Я надеюсь, что n3601 будет принят. :- )
В c++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();
Сделайте класс результата дочерним по отношению к классу шаблона. предполагая, что член указателя является объектом вашего результирующего класса в public или любом другом, вы можете получить доступ к любым объектам, сделав что-то вроде этого
template <stuff for this class> :: public result { blah }