获取具有指向成员的指针的成员类型

时间:2017-09-17 10:48:35

标签: c++

我正在尝试编写一个接受任何类型的模板类,作为参数,它有一些可用作索引的公共成员(类型为int,short,unsigned等)。我希望我的模板类接受要使用的对象类型以及我的模板类应该使用此类型字段的信息作为'键'领域。

我写了类似下面的内容(只是一个例子,让你知道我想如何使用它),但它不起作用。问题是我正在尝试使用指向成员的指针作为我的模板类用于获取Key的指定为Value的类型字段的信息。我想使用decltype来获取指向字段的类型,但它不起作用。

有没有办法获得poiter指向成员的字段类型?我尝试过衰减功能但没有成功。而不是" int A :: *"我想得到" int"。

#include <iostream>
#include <vector>
using namespace std;

template <class V, class M, M member>
struct MyClass
{
    using key_type = decltype(member);
    vector<key_type> v;

    MyClass()
    {
        v.push_back(1);
        // ERROR - error: no matching function for call to 'std::vector<int A::*, std::allocator<int A::*> >::push_back(int)'
    }
};

struct A 
{ 
    int x; 
    int key;
};

int main()
{
    MyClass<A, decltype(&A::key), &A::key> mc;
}

1 个答案:

答案 0 :(得分:1)

TL; DR :对模板参数进行一些小修改:

template <class C, typename Mem, Mem C::*member>
struct MyClass {
    using key_type = Mem;
    vector<key_type> v;

    MyClass()
    {
        v.push_back(1);
    }
};

实例化:

MyClass<A, decltype(A::key), &A::key> mc;

会做的伎俩。

说明:

  1. 您希望第三个参数是指向您作为第一个参数传递的类成员的指针。这需要指向成员语法C::*的指针。类型Mem是“指针”的类型。

  2. 要获取成员的类型,而不是“指向成员的指针”的类型,您需要为decltype提供成员访问表达式或限定ID。因此,那里的变化。

  3. 您可以将模板参数的数量减少到2,方法是只将指针传递给成员类型(如您最初所做的那样),并使用元函数从中提取相关信息。

    template<typename T>
    struct point_to_mem;
    
    // Meta-function to extract type information from a pointer to a member.
    template<class C, typename T>
    struct point_to_mem<T C::*> {
        using member_type = T;
        using class_type  = C;
    };
    
    template <typename PointToMem, PointToMem member>
    struct MyClass {
        using key_type = typename point_to_mem<PointToMem>::member_type;
        vector<key_type> v;
    
        MyClass()
        {
            v.push_back(1);
        }
    };
    
    // ...
    
    MyClass<decltype(&A::key), &A::key> mc;
    

    最后,使用C ++ 17,您可以非常经济地将模板参数减少到1:

    template <auto member>
    struct MyClass {
        using key_type = typename point_to_mem<decltype(member)>::member_type;
        // As before
    };
    
    // ...
    
    int main()
    {
        MyClass<&A::key> mc;
    }