Смешивание псевдонимов и шаблонных специализаций - PullRequest
2 голосов
/ 03 мая 2019

Я пытаюсь найти лучший метод, чтобы иметь своего рода «объект», который может быть либо специализированным, либо «связанным» с другим типом.

Например, вы не можете специализировать класс, чтобы он сталпростой int, и вы не можете использовать ключевое слово, используя для того, чтобы специализировать классы.

Мое решение следующее:

template<class Category, Category code>
struct AImpl
  {};

template<class Category, Category code>
struct AHelper
  {
  using type = AImpl<Category, code>;
  };

template<class Category, Category code>
using A = typename AHelper<Category, code>::type;

template<int code>
void doSomething(A<int, code> object)
  {
  }

template<>
struct AImpl<int, 5>
  { 
  double a; 
  };

template<>
struct AImpl<int, 6>
  { 
  int b; 
  double c;
  };

template<>
struct AHelper<int, 7>
  {
  using type = int;
  };

template<class Category, Category code>
struct Alternative {};

template<int code>
void doSomethingAlternative(Alternative<int, code> object)
  {
  }

Это работает, но вам нужно указать параметр кода в doSomething, и я бы хотел этого избежать.

Например,:

A<int,7> a7; // This is equivalent to int
a7 = 4;
A<int, 5> a5; // This is equivalent to AImpl<int,5>
a5.a = 33.22;
doSomething(a5); // This does not compile
doSomething<5>(a5); // This compiles but is bulky
Alternative<int,0> alt0;
doSomethingAlternative(alt0); // This compiles and is not bulky
                              // but you're forced to use class
                              // specializations only

Есть ли способ добиться того, чего я хочу?Можно изменить как doSomething, так и реализацию A.

1 Ответ

2 голосов
/ 03 мая 2019

Если вы пытаетесь настроить поведение doSomething в зависимости от типа, с которым он вызывается, вы не можете получить компилятор, определяющий вещи из AHelpr::type (как ранее ответил ). Но вы можете сказать ему, что ему нужно знать, предоставив точку настройки в виде черты . Например:

template<typename T>
void doSomething(T& object)
{
    auto code = SmthTriats<T>::code;
}

Это очень расширяемый, учитывая способность специализироваться SmthTriats:

template<typename> struct SmthTriats;

template<typename Category, Category code_>
struct SmthTriats<AImpl<Category, code_>> {
    static constexpr auto code = code_;
};

template<>
struct SmthTriats<int> {
    static constexpr auto code = 7;
};

Класс черт допускает настройку и вне вашего модуля. Код клиента должен специализироваться только на SmthTriats со своим собственным типом, и, пока они уважают контракт, который вы заключили с вашей чертой, ваш код будет работать для них.

...