用c++模板编译类成员变量
Compiling Class Member Variables Out with C++ Templates?
我有一个类,看起来像这样:
class Compound
{
void* pValue0;
void* pValue1;
void* pValue2;
void* pValue3;
void* pValue4;
void* pValue5;
void* pValue6;
void* pValue7;
void* pValue8;
void* pValue9;
void* pValueA;
void* pValueB;
void* pValueC;
};
当我创建一个新的复合类,我分配额外的内存[sizeof(Compound) + extraSpace]。每个pValue都指向额外内存中的一个地址。
现在,我想根据需要减少pValue的数量。模板看起来很合适。
所以如果我想要一个类Compound<0A>,我只需要pValue0和pValueA,然后让编译器删除所有其他的pvalue。本质上,我希望它变成:
template <uint Mask = 0A>
class Compound<Mask>
{
void* pValue0;
void* pValueA;
}
这可能吗?我接近了enable_if,但是当我试图将其限制为特定的掩码时,当enable_if大小写为false时,编译器会抛出关于无法找到类型的错误。
谢谢大家!
可以这样做:
template<char...>
struct flags_tag {constexpr flags_tag(){}; };
template<char...Cs>
struct make_flags{ using type=flags_tag<Cs...>; };
template<char...Cs>
struct make_flags<'0','x',Cs...>:make_flags<Cs...>{};
template<char...Cs>
struct make_flags<'0','X',Cs...>:make_flags<Cs...>{};
template<char...Cs>
using make_flags_t = typename make_flags<Cs...>::type;
template<char...Cs>
constexpr make_flags_t<Cs...> operator""_flag(){ return {}; }
template<char> struct pValue_t;
template<> struct pValue_t<'0'>{ void* pValue0 = 0; };
template<> struct pValue_t<'1'>{ void* pValue1 = 0; };
// ...
template<> struct pValue_t<'A'>{ void* pValueA = 0; };
template<> struct pValue_t<'B'>{ void* pValueB = 0; };
template<> struct pValue_t<'C'>{ void* pValueC = 0; };
template<class flags>
struct Compound;
template<char...Cs>
struct Compound< flags_tag<Cs...> >:
pValue_t<Cs>...
{};
然后像这样使用:
using my_type = Compound< decltype( 0x0A_flag ) >;
int main() {
my_type test;
std::cout << test.pValue0 << test.pValueA << 'n';
}
似乎做你想做的。
我还会禁用Compound
类型的复制/移动函数,并使其其他构造函数private
具有friend
工厂功能。
请注意,这段代码可以生成指数数量的类(2^12,或4k),这可能导致二进制膨胀(如果任何每个类的代码没有内联而不存在)。
(生活例子)std::conditional
类似于std::enable_if
,除了条件总是返回一个类型。
std::conditional<satisfies(Mask), void*, EmptyClass>
将是有条件地交换成员类型并使其编译的方法。
问题是,c++不允许空成员。大小为1。要解决这个问题,需要使用空成员优化。这将实现您所要求的内存布局,但不幸的是,这将使类成员难以阅读。如果您认为值得这样做,可以添加访问器函数来缓解这种情况。
我假设Compound
类应该包含指向不同类的对象的指针,而不是void指针,正如你在评论中所说的。
我不知道这是不是一个好主意,因为我认为在设计中有一些错误,但你可以在ints
上使用元组和模板专门化来选择你想要的类型:
class Class0;
class ClassA;
template<int> struct Compound {};
template<> struct Compound<0A>
{
typedef std::tuple<Class0*, ClassA*> type;
}
// other mapping from mask to type
typename Compound<0A>::type aCompund(ptr0, ptrA);
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 内置函数可查看CPP中的成员变量
- 是否可以初始化不可复制类型的成员变量(或基类)
- 将包含C样式数组的对象初始化为成员变量(C++)
- 为什么我不能在一个类的不同行中声明和定义成员变量?
- 在循环中按顺序遍历成员变量
- c++类声明时,相同的例程,不同的成员变量类型
- 如何从另一个文件继承私有成员变量和公共函数
- 在C++类中,是否必须初始化作为数组的成员变量
- 如何从子成员函数修改父公共成员变量
- 我可以在 C++ 中将数据成员/变量从其定义之外添加到结构中吗?
- 从私有成员变量的成员方法返回unique_ptr
- 在派生类中使用基类的私有成员变量的最佳方法
- 静态 constexpr 类成员变量对多线程读取是否安全?
- C++:是否可以使用非静态成员变量模板?
- 打印所有继承的类成员变量和方法
- 如何在复杂继承中访问静态成员变量
- 为什么我不能在返回 const 的布尔函数中为类成员变量赋值?C++
- 成员变量与函数概念检查