是否可以执行以下操作:
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? 我想根据一些可以在编译时检查的条件来更改类的结构。有什么办法可以做到这一点?
答案 0 :(得分:4)
您不能为此使用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>
{ ... };
答案 1 :(得分:1)
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和getters ...可能具有不同的签名。受保护的辅助函数可以为对象提供bool API,以分隔实现。
最后,我不建议使用布尔值,而是希望枚举,因为它可以具有多个值。
如果仅扩展新版本,则也可以从早期版本继承。有了一些默认的模板参数,您甚至可以做更多花哨的事情。
请注意,这种向后兼容性可能很快就会变得复杂。有时,最好将完整的代码复制到旧版本中并保持原样,而又不干扰新的API。这是以重复代码为代价的。