class 专业化,没有用作专业化模板参数的 class 的模板参数
class specialization, without the template arguments of the class that is used as template argument for specialization
我目前在一个地理图书馆工作,我想要一个 general-purpose 向量 class 可以用于 lat/lng 点和投影点。
lat/lng 点的方向由方位角和长度描述,投影 space 中的方向由二维向量和长度描述。
所以 class 应该是这样的:
template <typename T>
struct vector {
direction_t direction;
lenght_t length;
};
lat/lng点定义为:
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;
};
并且对 latlng
和 point
都有 direction_trait
的特化,而无需为 latlng
和 latlng
的每个可能的模板参数定义特化point
。
我怎么能有这样的东西:
template <typename T>
struct direction_trait;
template <latlng>
struct direction_trait {
using direction_t = double;
};
我不想将与方向相关的信息添加到定义了 latlng
或 point
的 header。
(我在写这个问题的时候已经想出了解决方法,但是如果没有那个帮手有更优雅的方法解决这个问题class我会很乐意知道了)
我想出的解决方案如下,使用仅用于专业化的 class 的声明,以及对 class 的 class 的引用] latlng(点)的主体,使用 using trait = latlng_trait;
。该别名随后由矢量使用并获取方向类型。
经纬度 class:
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;
};
以下随心所欲:
#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>);
我目前在一个地理图书馆工作,我想要一个 general-purpose 向量 class 可以用于 lat/lng 点和投影点。
lat/lng 点的方向由方位角和长度描述,投影 space 中的方向由二维向量和长度描述。
所以 class 应该是这样的:
template <typename T>
struct vector {
direction_t direction;
lenght_t length;
};
lat/lng点定义为:
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;
};
并且对 latlng
和 point
都有 direction_trait
的特化,而无需为 latlng
和 latlng
的每个可能的模板参数定义特化point
。
我怎么能有这样的东西:
template <typename T>
struct direction_trait;
template <latlng>
struct direction_trait {
using direction_t = double;
};
我不想将与方向相关的信息添加到定义了 latlng
或 point
的 header。
(我在写这个问题的时候已经想出了解决方法,但是如果没有那个帮手有更优雅的方法解决这个问题class我会很乐意知道了)
我想出的解决方案如下,使用仅用于专业化的 class 的声明,以及对 class 的 class 的引用] latlng(点)的主体,使用 using trait = latlng_trait;
。该别名随后由矢量使用并获取方向类型。
经纬度 class:
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;
};
以下随心所欲:
#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>);