mardi 24 avril 2018

Template metaprogramming. Conditional existence for class members

I wonder if it is possible to write a template class, having different members set in its compiled version.

For example, how it is achieved using inheritance:

/// 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 {
  data_type min;
  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> {
  data_type sum;

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

And, suppose I have the following constexpr functions

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

So, the question is whether it is possible to express in C++ something like this:

template<DataType data_type>
struct Stats {
  size_t count;
  data_type min; // Must exist only in those instances, where IsMinMaxSupported(data_type) == true
  data_type max; // Must exist only in those instances, where IsMinMaxSupported(data_type) == true
  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);
    }
  }
};

Meaning that some of the fields mustn't physically exist in some cases (it is crucial for memory consumption). If it is possible, then will be method Describe() compiled as I wrote it, or should it have been rewritten (with proper specializations), using SFINAE?

Aucun commentaire:

Enregistrer un commentaire