有条件地在 class 中创建成员
Conditionally creating members inside a class
是否可以这样做:
template <unsigned majorVer, unsigned minorVer>
class Object
{
public:
if constexpr ((majorVer == 1) && (minorVer > 10))
bool newField;
else
int newInt
};
或
template <unsigned majorVer, unsigned minorVer>
class Object
{
public:
if constexpr ((majorVer == 1) && (minorVer > 10))
bool newField;
// Nothing other wise
};
使用 c++17?
我想根据可以在编译时检查的某些条件更改 class 的结构。有什么办法可以做到这一点?
您不能为此使用 if constexpr
。您必须使用 std::conditional
:
之类的方法将它们折叠成一个成员
std::conditional_t<(majorVer == 1) && (minorVer > 10), bool, int> newField;
或者,您可以将两种字段分别包装在它们自己的类型中:
struct A { bool newField; };
struct B { int newInt; };
并且要么从 std::conditional_t<???, A, B>
继承,要么将其中之一作为成员。
对于你想要一个成员或者什么都不想要的情况,另一种情况只需要是一个空类型。在 C++20 中,即:
struct E { };
[[no_unique_address]] std::conditional_t<some_condition(), bool, E> newField;
在 C++17 及更早版本中,您需要继承它以确保空基优化开始:
struct B { bool field; };
struct E { };
template <unsigned majorVer, unsigned minorVer>
class Object : private std::conditional_t<some_condition(), B, E>
{ ... };
if-constexpr 是关于控制流的,而不是关于内存布局的。也许反射 TS 很适合这个。但是,在可用之前,您将需要其他技术。
constexpr bool useLegacyInt(unsigned major, unsigned minor)
{
return (majorVer <= 1) && (minorVer <= 10));
}
template<bool>
class ObjectBase
{
book newField;
};
template<>
class ObjectBase<true>
{
int newInt;
};
template <unsigned majorVer, unsigned minorVer>
class Object : public ObjectBase<useLegacyInt (majorVer, minorVer)>
{};
在此基础上,您可以做一些改进。您不仅会影响成员,还会影响方法。所以 setter 和 getter 也可以有不同的签名。受保护的辅助函数可以为 Object 提供一个 bool API 来分隔实现。
最后,我不建议使用 bool,我更希望使用枚举,因为它可以有多个值。
如果新版本只是扩展,也可以从早期版本继承。使用一些默认模板参数,您甚至可以做更多花哨的事情。
请注意,这种向后兼容性很快就会变得复杂。有时最好只复制遗留版本中的完整代码并保持原样,而不受新版本的干扰 API。这是以重复代码为代价的。
是否可以这样做:
template <unsigned majorVer, unsigned minorVer>
class Object
{
public:
if constexpr ((majorVer == 1) && (minorVer > 10))
bool newField;
else
int newInt
};
或
template <unsigned majorVer, unsigned minorVer>
class Object
{
public:
if constexpr ((majorVer == 1) && (minorVer > 10))
bool newField;
// Nothing other wise
};
使用 c++17? 我想根据可以在编译时检查的某些条件更改 class 的结构。有什么办法可以做到这一点?
您不能为此使用 if constexpr
。您必须使用 std::conditional
:
std::conditional_t<(majorVer == 1) && (minorVer > 10), bool, int> newField;
或者,您可以将两种字段分别包装在它们自己的类型中:
struct A { bool newField; };
struct B { int newInt; };
并且要么从 std::conditional_t<???, A, B>
继承,要么将其中之一作为成员。
对于你想要一个成员或者什么都不想要的情况,另一种情况只需要是一个空类型。在 C++20 中,即:
struct E { };
[[no_unique_address]] std::conditional_t<some_condition(), bool, E> newField;
在 C++17 及更早版本中,您需要继承它以确保空基优化开始:
struct B { bool field; };
struct E { };
template <unsigned majorVer, unsigned minorVer>
class Object : private std::conditional_t<some_condition(), B, E>
{ ... };
if-constexpr 是关于控制流的,而不是关于内存布局的。也许反射 TS 很适合这个。但是,在可用之前,您将需要其他技术。
constexpr bool useLegacyInt(unsigned major, unsigned minor)
{
return (majorVer <= 1) && (minorVer <= 10));
}
template<bool>
class ObjectBase
{
book newField;
};
template<>
class ObjectBase<true>
{
int newInt;
};
template <unsigned majorVer, unsigned minorVer>
class Object : public ObjectBase<useLegacyInt (majorVer, minorVer)>
{};
在此基础上,您可以做一些改进。您不仅会影响成员,还会影响方法。所以 setter 和 getter 也可以有不同的签名。受保护的辅助函数可以为 Object 提供一个 bool API 来分隔实现。
最后,我不建议使用 bool,我更希望使用枚举,因为它可以有多个值。
如果新版本只是扩展,也可以从早期版本继承。使用一些默认模板参数,您甚至可以做更多花哨的事情。
请注意,这种向后兼容性很快就会变得复杂。有时最好只复制遗留版本中的完整代码并保持原样,而不受新版本的干扰 API。这是以重复代码为代价的。