специализация класса, без аргументов шаблона класса, который используется в качестве аргумента шаблона для специализации - PullRequest
0 голосов
/ 14 января 2020

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

Направление точек широты и долготы ist описывается азимутом и длиной, а единица в проецируемом пространстве - двумерным вектором и длиной.

Таким образом, класс должен выглядеть следующим образом:

template <typename T>
struct vector {
    direction_t direction;
    lenght_t length;
};

Определена точка широты / долготы как:

template <angle_unit T>
struct latlng {
  …
};

И точка определяется как:

template <typename projection_t,typename T = double>
struct point {
   …
};

Поэтому моей первоначальной идеей было определить direction_t как direction_trait<T>::direction_type direction:

template <typename T>
struct vector {
    using direction_t = direction_trait<T>::direction_type;

    direction_t direction;
    lenght_t length;
};

И иметь специализацию direction_trait для latlng и point, без необходимости определять специализацию для каждого из возможных параметров шаблона для latlng и point.

Как я могу получить что-то вроде:

template <typename T>
struct direction_trait;


template <latlng>
struct direction_trait {
    using direction_t = double;
};

Я не хочу добавлять информацию, связанную с направлением, к заголовку, где определено latlng или point.

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

Ответы [ 2 ]

1 голос
/ 14 января 2020

Следующее работает как вы sh:

#include <type_traits> // only for is_same_v in the tests

using angle_unit = int; // just so it compiled
template <angle_unit T>
struct latlng {
};

template <typename projection_t, typename T = double>
struct point {
};

template<typename T>
struct direction_trait;

template<angle_unit T>
struct direction_trait<latlng<T>> {
    using direction_type = double;
};

template<typename projection_t, typename T>
struct direction_trait<point<projection_t, T>> {
    using direction_type = T; // Or whatever you want
};

template <typename T>
struct vector {
    using direction_t = typename direction_trait<T>::direction_type;

    direction_t direction;
};

// Usage
static_assert(std::is_same_v<vector<latlng<5>>::direction_t, int>);
static_assert(std::is_same_v<vector<point<long>>::direction_t, double>);
static_assert(std::is_same_v<vector<point<long, float>>::direction_t, float>);
0 голосов
/ 14 января 2020

Я пришел к следующему решению: использовать объявление класса, который используется исключительно для специализации, и ссылку на этот класс для тела класса latlng (точка), используя using trait = latlng_trait;. Этот псевдоним затем используется вектором для получения типа направления.

Класс latlng:

struct latlng_trait; // a declaration of a class solely used for template specialization

template <angle_unit T>
struct latlng {
    using trait = latlng_trait;

    …
}

Специализация для latlng:

template <>
struct direction_trait<latlng_trait> {
    using direction_t = double;
};

Вектор:

template <typename T>
struct vector {
    typename direction_trait<typename T::trait>::direction_t direction;
};
...