有条件地在 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。这是以重复代码为代价的。