类专业化,没有用作专业化模板参数的类的模板参数

时间:2020-01-14 19:35:10

标签: c++ templates c++20

我目前在地理图书馆工作,我想有一个通用的矢量类,可用于经纬度点和投影点。

经度和纬度点的方向由方位角和长度来描述,而投影空间中的经度方向由2d向量和长度来描述。

所以类应该看起来像:

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_traitlatlng都具有point的特殊化,而无需为latlng和{{ 1}}。

我怎么有类似的东西:

point

我不想将与方向相关的信息添加到定义了template <typename T> struct direction_trait; template <latlng> struct direction_trait { using direction_t = double; }; latlng的标题中。

(我在编写问题时已经想出了一种解决方法,但是,如果有一种更优雅的方法来解决该问题,没有该助手类,我将很高兴知道它)

2 个答案:

答案 0 :(得分:1)

以下内容可按您的意愿进行:

#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>);

答案 1 :(得分:0)

我想出的解决方案如下:使用仅用于专业化的类的声明,并使用point使用latlng(点)的类体对该类的引用。然后,矢量将使用此别名获取方向类型。

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;

    …
}

向量:

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