Наследование псевдонимов типов в шаблонных классах - PullRequest
0 голосов
/ 17 февраля 2020

Я хочу сделать что-то вроде этого:

  • Моя библиотека определяет структуру LibStruct
  • Клиенты библиотеки создают свои собственные структуры, которые как-то связаны (в примере , Я использовал наследование, но, возможно, есть лучший способ выражения)
  • В библиотеке есть метод, который выполняет некоторые операции с использованием этих структур
  • Избегайте вызовов виртуальных функций (жесткое требование) и избегайте объединения / вариантов (мягкое требование)

То, что я делал до сих пор, таково:

template <typename T /** And a bunch more **/>
struct LibStruct {
  using Scalar = T;
  // And a bunch more aliases

  // Some data
};

template <typename T>
struct ClientStuctA : LibStruct<T> {
  using Scalar = T; // Can this be avoided?

  Scalar moreData;
};

struct ClientStuctB : LibStruct<double> {
  using Scalar = double; // Can this be avoided?

  Scalar otherData;
};

template <typename Whatever>
typename Whatever::Scalar doSomething(const Whatever& input) {
  // Do stuff
  return Whatever::Scalar();
}

Моя проблема в том, что все структуры клиента должны переопределять все псевдонимы. так что doSomething может их использовать. Есть ли способ избежать необходимости в этом?

(запрашиваю C++14, но если есть решение C++17, я тоже его приму)

1 Ответ

2 голосов
/ 17 февраля 2020

Итак, чтобы подвести итог, я и @ N.Shead были в комментариях, поддерживаемых этими ссылками о том, почему вы не можете сделать это лучше:

Распространение 'typedef' из на основе производного класса для «шаблона»

Наследование и шаблоны в C ++ - почему наследуемые члены невидимы?

Кажется, это лучшее, что мы можем сделать :

#include <iostream>

template<typename T /* And a bunch more */>
struct LibStruct {
  using Scalar = T;
  // ... and a lot more aliases
};

#define LIBSTRUCT_TYPES(base)           \
  using Scalar = typename base::Scalar; \
  // ... and a lot more

template<typename T>
struct ClientStuctA : LibStruct<T> {
  LIBSTRUCT_TYPES(LibStruct<T>)

  Scalar moreData;
  // OtherTypes moreDefinitions();

  Scalar func1() { return Scalar(2) * 3; }
  Scalar func2();
};

template<typename T>
typename ClientStuctA<T>::Scalar ClientStuctA<T>::func2() {
  return 5;
}

int main() {
  std::cout << ClientStuctA<int>().func1() << std::endl;
  std::cout << ClientStuctA<int>().func2() << std::endl;
  return 0;
}
...