c++ - 类成员的 C++ 条件布局
问题描述
我希望根据模板参数重新排列班级成员
class Empty1 { };
class Empty2 { };
class Empty3 { };
class Empty4 { };
class Empty5 { };
class Empty6 { };
class Layout1 { public: uint32_t val1; float val2; bool val3; };
class Layout2 { public: uint32_t val1; bool val3; float val2; };
class Layout3 { public: float val2; uint32_t val1; bool val3; };
class Layout4 { public: float val2; bool val3; uint32_t val1; };
class Layout5 { public: bool val3; uint32_t val1; float val2; };
class Layout6 { public: bool val3; float val2; uint32_t val1; };
template<uint8_t I>
class Item :
public std::conditional<(I % 6) == 0, Layout1, Empty1>::type,
public std::conditional<(I % 6) == 1, Layout2, Empty2>::type,
public std::conditional<(I % 6) == 2, Layout3, Empty3>::type,
public std::conditional<(I % 6) == 3, Layout4, Empty4>::type,
public std::conditional<(I % 6) == 4, Layout5, Empty5>::type,
public std::conditional<(I % 6) == 5, Layout6, Empty6>::type
{
public:
uint32_t getVal1() const { return val1; }
float getVal2() const { return val2; }
bool getVal3() const { return val3; }
};
这个例子应该产生不同的 val1,val2,val3 顺序,因此在不同的 I 值上有不同的内存布局所有所有成员在任何情况下都存在,但是即使没有使用类,我在 Visual Studio 中也不断收到错误 C3861 我该如何修复它,或者也许有人知道另一种方法?
GCC 错误信息
prog.cpp: In member function ‘uint32_t Item<I>::getVal1() const’:
prog.cpp:28:39: error: ‘val1’ was not declared in this scope
uint32_t getVal1() const { return val1; }
^~~~
prog.cpp: In member function ‘float Item<I>::getVal2() const’:
prog.cpp:29:36: error: ‘val2’ was not declared in this scope
float getVal2() const { return val2; }
^~~~
prog.cpp: In member function ‘bool Item<I>::getVal3() const’:
prog.cpp:30:35: error: ‘val3’ was not declared in this scope
bool getVal3() const { return val3; }
^~~~
解决方案
这与依赖基类有关。因为模板的基类依赖于模板参数,所以基类名称是依赖名称。发生这种情况时,编译器无法轻易知道该名称val1
是否是从基类继承的。
因此,您必须使用它继承的基类明确限定这些名称。当然,这有点困难,因为您尝试实现整个事情的方式。
使用包含而不是继承会更好,因为无论如何您都必须限定名称。而且您不需要所有那些空结构;您只需要从类型列表中进行选择:
struct Layout1 { std::uint32_t val1; float val2; bool val3; };
struct Layout2 { std::uint32_t val1; bool val3; float val2; };
struct Layout3 { float val2; std::uint32_t val1; bool val3; };
struct Layout4 { float val2; bool val3; std::uint32_t val1; };
struct Layout5 { bool val3; std::uint32_t val1; float val2; };
struct Layout6 { bool val3; float val2; std::uint32_t val1; };
//The tuple is here just as a convenient type-list mechanism.
using LayoutList = std::tuple<Layout1, Layout2, Layout3, Layout4, Layout5, Layout6>;
template<uint8_t I>
struct Item
{
using DataType = std::tuple_element_t<I % 6, LayoutList>;
DataType val;
uint32_t getVal1() const { return val.val1; }
float getVal2() const { return val.val2; }
bool getVal3() const { return val.val3; }
};
但是,如果您绝对必须使用基类,则可以使用类似的类型列表:
template<uint8_t I>
using ItemDataType = std::tuple_element_t<I % 6, LayoutList>;
template<uint8_t I>
struct Item : ItemDataType<I>
{
uint32_t getVal1() const { return ItemDataType<I>::val1; }
float getVal2() const { return ItemDataType<I>::val2; }
bool getVal3() const { return ItemDataType<I>::val3; }
};
推荐阅读
- python - How to create table with dynamically rows and columns with number of fields in template Django
- go - how do i minimize the amount if/else without losing any functionality?
- javascript - 制作不同大小的魔方
- android - 我应该在paypal check android sdk的用户名和密码字段中输入什么?
- pyspark - 如何在 pyspark 中进行一种热编码
- c# - WCF Webservice 使用 Stream 传递 messagecontract 并将字符串返回给客户端
- blockchain - OS X 中外部 SSD 上的比特币核心
- python - 动态检索包目录的绝对路径
- firebase - 非谷歌服务器上的 Firebase 云功能
- typescript - 升级到 typescript 4.4.2 后如何修复“错误‘JSX’未定义 no-undef’