将指向类的成员传递为模板参数

时间:2015-08-20 13:05:12

标签: c++ templates

我想编写一个将进程应用于类成员的函数。以下代码正在运行:

class AA
{
public:
    AA(){};
    ~AA(){};
    std::string type="AA";
};

class BB
{
public:
    BB(){};
    ~BB(){};
    template <typename T, typename TT>
    void test(T& a, TT(T::*memberPtr))
    {
        std::cout<<"test: "<<(a.*memberPtr)<<std::endl;
    }
    std::string type="BB";
};

int main()
{
    AA a;
    BB b;
    b.test(a, &AA::type);
}

但是我在编译时知道所有内容所以我想知道是否有可能写一些等效的东西但只能用模板?所以我可以这样写:

b.test<&AA::type>(a);

调用test(a):

std::cout<<"test: "<< (a.*MEMBER) <<std::endl; // MEMBER is given in template

或类似的东西。

3 个答案:

答案 0 :(得分:6)

您不能只执行test<&AA::type>,因为您还需要告诉功能模板您指向成员的指针是什么类型期待。典型的模式是:

template <class M, M member, class T> // deduced go last
void test(T& a) {
    cout << (a.*member);
}

使用方法:

test<decltype(&AA::type), &AA::type>

我相信目前有提议减少那里的冗长,但在那之前,它并不是世界上最糟糕的事情,你可以随时:

#define TYPE_AND_VAL(foo) decltype(foo), foo
test<TYPE_AND_VAL(&AA::type)>

我提到的提案是在C ++ 17中,并允许你这样做:

template <auto member, class T>
void test(T& a) {
    cout << (a.*member);
}

test<&AA::type>(a);

答案 1 :(得分:2)

这与谢拉德的答案有关,但妥协是通过你的班级和一个lambda。编译器能够to inline the lambda,因此您可能无法在运行时付费:

struct BB
{
public:
    template <typename T, typename F>
    void test(T& a, F f)
    {
        std::cout<<"test: "<< f(a) <<std::endl;
    }
    std::string type="BB";
};

int main()
{
    AA a;
    BB b;
    b.test(a, [](AA& a){return a.type;});
}

您可能(或可能不会)比使用指向类成员的指示更清楚。

答案 2 :(得分:0)

完全消除这种有点强烈的类型。而不是请求用户为您提供类和成员poiner,只需接受模板化仿函数并调用它的operator()。这将是最灵活,最简洁的。