如何解析成员指针非类型模板参数的组件类型

时间:2016-02-08 04:19:01

标签: c++ templates c++11

在下面的示例代码中,B类有三个模板参数。我想知道前两个论点是否可以从第三个论证中推断出来,我认为它包含了所有必要的信息。现在我正在使用一个宏,以避免在各种组合中多次繁琐地重复相同的名称。我认为应该有更好的方法。

main 中,我展示了我想写的理想内容。

B类的目标是: 1)变量成员指针应明确地是类的非类型模板参数 2)它应该适用于不同的类(例如A1,A2)和不同类型的成员变量。 如何重写B类以实现上述目标并允许仅使用一个模板参数进行定义?

#include <iostream>

struct A1
{
    int m_n;
    A1() : m_n(10) {}
};

struct A2
{
    double m_x;
    A2() : m_x(2.1) {}
};

#define XXX(cls, member) cls, decltype(cls::member), &cls::member

// I would like B to have only the last template argument
template <typename C, typename T, T C::*P>
struct B
{
    B(C& cls) : m_c(cls), m_v(cls.*P) {};
    void set(T v) { m_v = v; }
    void save() { m_c.*P = m_v; }
    C& m_c;
    T m_v;
};

int main()
{
    A1 a1; std::cout << "a1.n=" << a1.m_n << std::endl;
    A2 a2; std::cout << "a2.x=" << a2.m_x << std::endl;

    // This is what I write
    typedef B<XXX(A1,m_n)> m1_n_t;
    typedef B<XXX(A2,m_x)> m2_x_t;
    // This is what I woukd like to write
    //typedef B<&A1::m_n> m1_n_t;
    //typedef B<&A2::m_x> m2_x_t;

    // this is how I use it
    m1_n_t b1(a1); b1.set(5); b1.save(); std::cout << "a1.n=" << a1.m_n << std::endl;
    m2_x_t b2(a2); b2.set(3.4); b2.save(); std::cout << "a2.x=" << a2.m_x << std::endl;

    return 0;
}

1 个答案:

答案 0 :(得分:4)

你会有这样的事情:

template <class Type>
struct member_object;

template<typename RetType, typename ClassType> 
struct member_object<RetType ClassType::*> {
    using return_type = RetType;
    using class_type = ClassType;
    using member_type = RetType ClassType::*;
};

Live demo

请注意,在A中,n是私有的,因此除非您将其公开,否则无法在decltype(&A::n)中进行编译。

如果在编译时需要实际的指针,那么你必须明确地将它作为另一个模板参数传递,如下所示:

template <class PtrType, PtrType Ptr>
struct member_object;

template<typename RetType, typename ClassType, RetType ClassType::* Ptr> 
struct member_object<RetType ClassType::*, Ptr> {
    using return_type = RetType;
    using class_type = ClassType;
    using member_type = RetType ClassType::*;
};