class 成员的 C++ 条件布局
C++ Conditional layout of class members
我希望 class 的成员根据模板参数重新排列
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 值会产生不同的内存布局
所有成员在任何情况下都存在,但即使不使用 class,我也会在 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; }
^~~~
这与依赖基础class有关。因为模板的基础 class(es) 依赖于模板参数,所以基础 class 名称是从属名称。发生这种情况时,编译器无法轻易知道名称 val1
是否继承自基 class.
因此,您必须显式使用其继承的基础class限定此类名称。当然,这有点困难,因为您尝试实施这整件事的方式。
使用包含而不是继承会好得多,因为无论如何您都必须限定名称。而且您不需要所有这些空结构;你只需要从类型列表中 select:
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; }
};
但是,如果您绝对必须使用基数,则可以使用类似的类型列表 class:
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; }
};
我希望 class 的成员根据模板参数重新排列
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 值会产生不同的内存布局 所有成员在任何情况下都存在,但即使不使用 class,我也会在 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; }
^~~~
这与依赖基础class有关。因为模板的基础 class(es) 依赖于模板参数,所以基础 class 名称是从属名称。发生这种情况时,编译器无法轻易知道名称 val1
是否继承自基 class.
因此,您必须显式使用其继承的基础class限定此类名称。当然,这有点困难,因为您尝试实施这整件事的方式。
使用包含而不是继承会好得多,因为无论如何您都必须限定名称。而且您不需要所有这些空结构;你只需要从类型列表中 select:
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; }
};
但是,如果您绝对必须使用基数,则可以使用类似的类型列表 class:
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; }
};