Добавить специализированные методы в шаблон класса без SFINAE - PullRequest
0 голосов
/ 20 апреля 2020

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

// A vector of linear algebra
template <int n>
struct Vector
{
    // A bunch of functions not relying on a specific value for n
    float norm() { ... }
    float dot(const Vector& other) { ... }
private:
    float _data[n];
};

Это все хорошо, но трехмерные векторы, в частности, имеют двухкомпонентное перекрестное произведение, в то время как векторы в других измерениях нет (ну, некоторые делают, но это не то, что это около). Я мог бы использовать SFINAE, чтобы функция cross была определена только для n = 3, однако я бы предпочел иметь возможность определять все функции, которые не зависят от определенного значения c вместе, а затем реализовать остальное в независимых шаблонных специализациях.

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

template <>
struct Vector<3> : public Vector<3> // error: invalid use of incomplete type ‘struct Vector<3>’
{
    Vector cross(const Vector& other) { ... }
};

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

Есть ли альтернатива SFINAE или это мой единственный вариант?

Ответы [ 2 ]

1 голос
/ 20 апреля 2020

Вы можете использовать общий псевдоним шаблона для добавления дополнительных функций, если выполняется условие.

template <int n>
struct Vector_impl {
    // base implementation
}

struct Vector_3_impl : Vector_impl<3> {
    // n == 3 specific implementation
}

template <int n>
using Vector = std::conditional_t<n == 3, Vector_3_impl, Vector_impl<n>>;
0 голосов
/ 20 апреля 2020

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

// common part
template <int N, bool = N==3>
struct Vect
 {
   float foo_1 () { return 1.0f; }

   float _data[N];
 };

// additional methods for N==3 only
template <int N>
struct Vect<N, true> : public Vect<N, false>
 {
   float foo_2 () { return 2.0f; }

   // other additional methods
 };

, который вы можете использовать таким образом

   Vect<1>  v1;
   Vect<3>  v3;

   v1.foo_1();
   // v1.foo_2();  compilation error

   v3.foo_1();
   v3.foo_2();  // compile
...