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



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

我有以下示例:

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。

可能有两种可能的选项如下。

I. 向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>;

问题是指针不匹配:

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,这是所讨论数据的原始类型,所以这一次,强制转换不应该违反严格的混叠规则,我们应该避免未定义的行为(也请参阅这个问题,承认,标记 C,但通常,C 和 C++ 在这个特定问题上是兼容的(。

相关内容

  • 没有找到相关文章

最新更新