C++模板参数使用类成员问题:固定数组成员适配方案
解决模板类兼容数组成员指针的问题
嘿,这个问题我太清楚了!你的代码编译失败主要有两个核心问题,咱们一个个拆解,再给你改好的代码:
问题根源
- 成员指针类型不匹配:你的模板第二个参数声明的是
int* CONTAINER::*SomeMember,也就是“指向CONTAINER类中int*类型成员的指针”。但Bar1::y是int[42]类型的数组成员,它的成员指针类型是int (Bar1::*)[42]——这和模板要求的int*成员指针完全是两种不同的类型,编译器自然会报错。 value类型错误:你定义的int value;根本存不下数组或指针!不管是数组成员还是指针成员,你实际需要存储的是指向int的指针,所以value的类型应该改成int*。
解决方案(C++17及以上,最简洁)
利用C++17的auto非类型模板参数,让编译器自动推导成员指针的类型,再通过编译期判断处理数组和指针两种情况:
#include <type_traits> template<class CONTAINER, auto SomeMember> struct Foo { Foo(CONTAINER *container) : container(container), value(get_int_ptr(container)) {} private: // 编译期区分成员是指针还是数组,返回int* static int* get_int_ptr(CONTAINER* container) { if constexpr (std::is_pointer_v<decltype(container->*SomeMember)>) { return container->*SomeMember; } else { // 数组类型会自动退化为指向第一个元素的指针 return container->*SomeMember; } } public: CONTAINER *container; int* value; // 修正为int*类型,存储指针 }; // 原有的结构体保持不变 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; Foo<Bar1,&Bar1::y> foo3(&b1); // 现在正常编译 Foo<Bar2,&Bar2::y> foo2(&b2); // 正常编译 Foo<Bar3,&Bar3::x> foo(&b3); // 依然可以正常工作 }
兼容C11/C14的版本
如果需要支持更早的C++标准,可以用模板特化来处理不同类型的成员指针:
#include <type_traits> // 辅助模板,用于将不同类型的成员转换为int* template<typename MemPtr> struct MemberToIntPtr; // 特化:处理int*类型的成员指针 template<typename CONTAINER> struct MemberToIntPtr<int* CONTAINER::*> { static int* get(CONTAINER* container, int* CONTAINER::*mem_ptr) { return container->*mem_ptr; } }; // 特化:处理任意大小的int数组成员指针 template<typename CONTAINER, size_t N> struct MemberToIntPtr<int (CONTAINER::*)[N]> { static int* get(CONTAINER* container, int (CONTAINER::*mem_ptr)[N]) { return container->*mem_ptr; // 数组退化为指针 } }; // 主模板 template<class CONTAINER, typename MemPtr, MemPtr SomeMember> struct Foo { Foo(CONTAINER *container) : container(container), value(MemberToIntPtr<MemPtr>::get(container, SomeMember)) {} CONTAINER *container; int* value; }; void TEST() { Bar1 b1; Bar2 b2; Bar3 b3; // 使用时需要明确指定成员指针的类型 Foo<Bar1, int (Bar1::*)[42], &Bar1::y> foo3(&b1); Foo<Bar2, int (Bar2::*)[42], &Bar2::y> foo2(&b2); Foo<Bar3, int* Bar3::*, &Bar3::x> foo(&b3); }
关键修改点总结
- 把
value的类型从int改为int*,正确存储指向int的指针 - 用
auto模板参数(C++17)或模板特化,让模板兼容数组和指针两种成员类型 - 利用数组到指针的隐式转换,把数组成员转换为
int*使用
内容的提问来源于stack exchange,提问作者powerpete
相关产品推荐
相关产品推荐

