简体   繁体   中英

Is it possible to create different derived classes sharing the same methods that operate on member variables unique to each derived class?

I am writing an arbitrary-ranked tensor (multidimensional array) class in C++ and would like to have static and dynamic memory versions of it. However, I am struggling to think of a way to avoid having to duplicate methods in the static/dynamic versions of the class, considering that the underlying data containers would be different. I hope the following minimal example illustrates my point:

// Product function
template <typename ...data_type>
constexpr auto Product(data_type ..._values)
{
  return (_values * ...);
}

// Static memory version
template <class t_data_type, unsigned ...t_dimensions>
class StaticTensor
{
  private:
  std::array<t_data_type, Product(t_dimensions...)> Entries; // Store entries as contiguous memory

  public:
  StaticTensor() = default;
  ~StaticTensor() = default;

  void StaticMethod()
  {
    // Some code that operates on Entries.
  }
};

// Dynamic memory version
template <class t_data_type>
class DynamicTensor
{
  private:
  std::vector<t_data_type> Entries;

  public:
  DynamicTensor() = default;
  ~DynamicTensor() = default;

  template <typename ...t_dimensions>
  void Resize(t_dimensions ...dims)
  {
    Entries.resize(Product(dims...));
  }

  void DynamicMethod()
  {
    // Some code that operates on Entries.
  }
};

I have considered inheritance-based/polymorphic approaches, but it seems that I'd still have to implement separate methods in each of the specialised classes. I would ideally like all the methods to operate on the underlying iterators in std::array and std::vector , without having to worry about which data container they belong to. Can anyone suggest how I can go about doing this?

You can use CRTP techniques to create a TensorBase , then convert *this to Derived& to access the derived class's Entries inside Method() :

template <class Derived>
class TensorBase
{
 public:
  void Method()
  {
    auto& Entries = static_cast<Derived&>(*this).Entries;
    // Some code that operates on Entries.
  }
};

Then your StaticTensor/DynamicTensor can inherit TensorBase to obtain the Method() . In order to enable the base class to access private members, you also need to set the base class as a friend:

// Static memory version
template <class t_data_type, unsigned ...t_dimensions>
class StaticTensor
  : public TensorBase<StaticTensor<t_data_type, t_dimensions...>>
{
  using Base = TensorBase<StaticTensor<t_data_type, t_dimensions...>>;
  friend Base;
 private:
  std::array<t_data_type, Product(t_dimensions...)> Entries;

 public:
  StaticTensor() = default;
  ~StaticTensor() = default;
};

// Dynamic memory version
template <class t_data_type>
class DynamicTensor 
  : public TensorBase<DynamicTensor<t_data_type>>
{
  using Base = TensorBase<DynamicTensor<t_data_type>>;
  friend Base;
 private:
  std::vector<t_data_type> Entries;

 public:
  DynamicTensor() = default;
  ~DynamicTensor() = default;
};

Demo.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM