4

是否可以执行以下操作:

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?我想根据可以在编译时检查的某些条件来更改类的结构。有什么办法可以做到这一点?

4

2 回答 2

10

你不能用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>
{ ... };
于 2019-04-08T03:19:54.290 回答
2

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 来分离实现。

最后,我不建议使用布尔值,我更希望使用枚举,因为它可以有多个值。

如果仅扩展新版本,也可以从早期版本继承。使用一些默认模板参数,您甚至可以做更多花哨的事情。

请注意,这种向后兼容性可能会很快变得复杂。有时最好只复制旧版本中的完整代码并保持原样,而不受新 API 的干扰。这是以重复代码为代价的。

于 2019-04-08T06:24:55.000 回答