c ++使用类成员作为模板参数

时间:2018-05-29 13:03:20

标签: c++ templates pointer-to-member

我想要一个带有2个模板参数的模板类:一个Container类和一个指向值数组的成员指针。

我遵循示例:

template<class CONTAINER,int * CONTAINER::*SomeMember>
struct Foo {
    Foo(CONTAINER *container) {
        this->value = container->*SomeMember;
        this->container = container;
    }
    CONTAINER *container;
    int value;
};

struct Bar1 {
    char bla;
    int y[42];
};
struct Bar2 {
    int blablab;
    char bla;
    int y[42];
};
struct Bar3 {
    int * x;
};

void TEST() {
    Bar1 b1;
    Bar2 b2;
    Bar3 b3;

    //This one fails with
    // error: could not convert template argument '&Bar1::y' to 'int* Bar1::*'
    // error: invalid conversion from 'Bar1*' to 'int' [-fpermissive]
    Foo<Bar1,&Bar1::y> foo3(&b1);

    //This fails too
    Foo<Bar2,&Bar2::y> foo2(&b2);

    //This is working
    Foo<Bar3,&Bar3::x> foo(&b3);
}

只要我不使用固定大小的数组,这些东西就可以正常工作。

为了让这个例子有效,我需要纠正什么?对我来说最重要的部分是让这个例子与Bar1和Bar2一起使用。

2 个答案:

答案 0 :(得分:1)

可能有两个可能的选项,如下所示。

予。添加一个指向数组的Bar1的额外成员:

struct Bar1 {
    int y[42];
    int *z = y;
};
Foo<Bar1, &Bar1::z> foo1;

II。让Foo稍微更通用:

template<class, auto> struct Foo;
template<class Container, int *Container::*member> struct Foo<Container, member>;
template<class Container, int (Container::&member)[42]> struct Foo<Container, member>;

在C ++ 17之前,您需要添加第三个模板参数:

template<class, typename T, T member> struct Foo;
template<class Container, int *Container::*member> struct Foo<Container, int *Container::*, member>;

答案 1 :(得分:0)

问题是指针的不匹配:

Foo<Bar1, &Bar1::y>
          ^

Bar1::y的地址会产生以下类型的指针:

int(Bar1::*)[42];

我。即在指向大小为42的数组的指针中,而不是指向int的指针。投射指针有效:

Foo<Bar1, reinterpret_cast<int* Bar1::*>(&Bar1::y)> foo3(&b1);

但是,value(类型int)和container->*SomeMember(类型指向int的指针)仍然不兼容,因此您需要更改value的类型或取消引用指针:

value = *(container->*SomeMember);
//      ^ (!)

当然,reinterpret_cast总是很臭,但是当取消引用指针时会产生一个int,这是所讨论数据的原始类型,所以这一次,强制转换不应该违反严格的别名规则而我们应该避免未定义的行为(参见,question,承认,标记C,但通常,C和C ++在这个特定的事情上是兼容的。)