【问题标题】:Template metaprogramming. Conditional existence for class members模板元编程。类成员的条件存在
【发布时间】:2018-04-24 10:26:56
【问题描述】:

我想知道是否可以编写一个模板类,在其编译版本中设置不同的成员。

例如,如何使用继承来实现:

/// These statistics are supported for all data types
struct StatsBase {
  size_t count;

  virtual void Describe() { print(count); }
};

/// These can describe almost all data types, but not all of them
template<DataType data_type>
struct StatsMinMax : public StatsBase {
  CppType<data_type> min;
  CppType<data_type> max;

  void Describe() override {
    StatsBase::Describe();
    print(min);
    print(max);
  }
};

/// These are for numeric data types only
template<DataType data_type>
struct StatsAll : public StatsMinMax<data_type> {
  CppType<data_type> sum;

  void Describe() override {
    StatsMinMax<data_type>::Describe();
    print(sum);
  }
}

并且,假设我有以下 constexpr 函数

constexpr bool IsMinMaxSupported(data_type dt) { /* details */ }
constexpr bool IsSumSupported(data_type dt) { /* details */ }

所以,问题是是否可以用 C++ 表达如下:

template<DataType data_type>
struct Stats {
  size_t count;
  CppType<data_type> min; // Must exist only in those instances, where IsMinMaxSupported(data_type) == true
  CppType<data_type> max; // Must exist only in those instances, where IsMinMaxSupported(data_type) == true
  CppType<data_type> sum; // Must exist only in those instances, where IsSumSupported(data_type) == true

  void Describe() { 
    print(count);
    if (IsMinMaxSupported(data_type)) {
      print(min);
      print(max);
    }
    if (IsSumSupported(data_type)) {
      print(sum);
    }
  }
};

意味着某些字段在某些情况下不能物理存在(这对于内存消耗至关重要)。如果可能,那么方法 Describe() 会按照我编写的方式编译,还是应该使用 SFINAE 重写(具有适当的专业化)?

【问题讨论】:

  • 也许是一个愚蠢的问题:什么是 DataType ?是枚举吗?如果是,那么成员“data_type min”是什么?
  • @alangab 这对我来说看起来像是一个错字。 中第一个符号的唯一有效关键字是 classtypename
  • @alangab,是的,它是一个枚举。我这么写只是为了稍微简化代码,因为它无论如何都不会编译。我已经更正了代码

标签: c++ c++11 template-meta-programming sfinae


【解决方案1】:

可以通过模板特化来实现:

template<typename DataType, bool x_min_max_supported> struct
StatsMinMax { /* empty */ };

template<typename DataType> struct
StatsMinMax<DataType , true>
{
    DataType min;
    DataType max;
};

...

template<DataType data_type>
struct Stats
: public StatsMinMax<DataType, IsMinMaxSupported(data_type)>
{

【讨论】:

  • 答案很好。但是,如果您真的想要变量声明的 8 种不同排列的粒度,您可以考虑将其扩展到具有 3 个基类、每个变量 1 个的多重继承,或者如果您更喜欢级联而不是多重继承,则可以考虑将其扩展到模板类的级联。跨度>
  • 我有你,谢谢。但答案并不完整。主要关心的是字段,但问题是关于在方法中使用它们。
  • @Alexey 您可以将空的和非空的 Describe 方法放入这些类中。或使用if constexpr
  • 调整方法的最简单方法可能是实际定义缺少的成员,但定义为类型(空枚举)而不是值,或者定义 allong-side helper MemberExistsXxx 枚举,然后可以是如果 constexpr 使用 C++17 检测到。另一种方法是在基类中定义 getter 和 setter 方法,如果成员不存在,则返回默认值或错误/异常,因此即使值不存在,顶级代码也可以 get() ..
猜你喜欢
  • 2020-10-10
  • 1970-01-01
  • 1970-01-01
  • 2012-11-03
  • 2021-11-25
  • 1970-01-01
  • 2021-09-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多