指向类成员作为模板形参的指针

Pointer to class member as a template parameter

本文关键字:形参 指针 成员      更新时间:2023-10-16

我想使用指向类成员的指针作为模板形参,如下所示:

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

使用像MyStruct<SomeClass, SomeResult, &SomeClass::value> variable这样的结构体很好,但我不喜欢我必须指定SomeClassSomeResult

如果可能的话,我想使用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>,如果是,如何?

没有解决我的问题的相关问题:

  • 指向类成员作为模板参数的指针
  • c++ 0x的constexpr错误,返回模板函数

在c++17中,随着模板参数(P0127)中auto的添加,我认为您现在可以这样做:

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();

本文为下一个c++标准提出了一个答案:

  • https://isocpp.org/files/papers/n3601.html

建议使用以下语法:

template<using typename T, T t>
struct some_struct { /* ... */ };
some_struct<&A::f> x;

需要一个新的语法结构表明你现在不能这样做。

我希望n3601能被接受。: -)

这可能是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之前,我将此作为中间解决方案。

使结果类成为模板类的子类。假设指针成员是public或其他类型的结果类的对象,您可以通过以下操作访问任何对象

template <stuff for this class> :: public result
{
    blah
}