仅针对某些方法的模板专业化
Template specialization only for certain methods
我无法在我的 vec2 模板中专门化某些方法 class。这是我的代码:
#pragma once
template<typename Number>
struct vec2
{
static_assert(std::is_same<Number, int>::value
|| std::is_same<Number, float>::value
|| std::is_same<Number, double>::value,
"Type not allowed. Use <int>, <float> or <double>.");
Number x, y;
vec2();
vec2(Number x, Number y);
void add(const vec2& other);
inline Number lengthSquared() const;
/*Some other general methods like this two*/
}
我的问题是:我想以这种方式专门化我的 length
方法:
它必须 return a float
如果模板类型是 int
(vec2<int>
)
如果模板类型是 float
(vec2<float>
)
,它必须 return a float
它必须 return a double
如果模板类型是 double
(vec2<double>
)
我以前像这样专门化了我的 length
方法:
struct vec2
{
/* ... */
inline Number length() const;
}
/*Outside vec2 struct, but in vec2.h*/
template<> inline int vec2<int>::length() const;
template<> inline float vec2<float>::length() const;
template<> inline double vec2<double>::length() const;
然后在我的 .cpp 文件中实现了它。这工作正常,但它只能 return 相同的模板类型,它不能 return 一个 float length
一个 vec2<int>
。有办法吗?
您可以编写一个辅助类型,在给定向量组件类型的情况下为 length
提供 return 类型。
template<typename T>
struct vec_length_t {};
// Specializations:
template<>
struct vec_length_t<int> { using type = float; };
template<>
struct vec_length_t<float> { using type = float; };
template<>
struct vec_length_t<double> { using type = double; };
(或给它起一个更通用的名称以便在其他地方重复使用,例如 floatify
或类似名称)
然后像这样使用它:
template<typename Number>
struct vec2 {
...
typename vec_length_t<Number>::type length() const;
...
};
要重复用于多个函数或在同一个 class 中使用,您当然也可以使用本地类型别名:
template<typename Number>
struct vec2 {
...
using length_t = typename vec_length_t<Number>::type;
...
length_t length() const;
...
};
这使得在函数体中使用 length_t
来调用正确的 std::sqrt
重载变得很容易(你可能不想使用 double
重载即将 return 一 float
!):
template<typename Number>
vec2<Number>::length_t vec2<Number>::length() const {
// Note that x*x+y*y is a Number, but we want a length_t:
return std::sqrt(static_cast<length_t>(x*x + y*y));
// Or, if you have lengthSquared() defined as returning a Number:
return std::sqrt(static_cast<length_t>(lengthSquared()));
}
有几种可能的选择:
1) 使用某种形式的辅助特征模板为长度提供 return 类型:
如果只提供了你想在模板中存储的类型的特化(int、float、double),那么你可以去掉static_assert(尽管静态断言最在潜在错误消息的可读性方面可能有优势)
一个人还可以只为 int 提供此特征模板的专业化,并为其他所有内容提供通用版本,结合 static_assert 已经存在的工作方式相同,但少了两个专业化写,但在我看来,关于你的 class 处理的类型的知识将分布在两个地方(特征和静态断言)
2) 如果 'general' 情况(double 和 float)的实现是相同的,只有 int 情况不同 - 也可以使 public 长度调用私有长度重载 false_type/true_type 结果为 is_same :),可扩展性较差但不需要任何外部类型:
auto length() -> decltype(length(is_same<T, int>) { return length(is_same<T, int>); }
Number length(std::false_type) { .... }
float length(std::true_type) {....}
当然,使用 C++14 可以摆脱 decltype mambo-jambo。
我无法在我的 vec2 模板中专门化某些方法 class。这是我的代码:
#pragma once
template<typename Number>
struct vec2
{
static_assert(std::is_same<Number, int>::value
|| std::is_same<Number, float>::value
|| std::is_same<Number, double>::value,
"Type not allowed. Use <int>, <float> or <double>.");
Number x, y;
vec2();
vec2(Number x, Number y);
void add(const vec2& other);
inline Number lengthSquared() const;
/*Some other general methods like this two*/
}
我的问题是:我想以这种方式专门化我的 length
方法:
它必须 return a float
如果模板类型是 int
(vec2<int>
)
如果模板类型是 float
(vec2<float>
)
,它必须 return a float
它必须 return a double
如果模板类型是 double
(vec2<double>
)
我以前像这样专门化了我的 length
方法:
struct vec2
{
/* ... */
inline Number length() const;
}
/*Outside vec2 struct, but in vec2.h*/
template<> inline int vec2<int>::length() const;
template<> inline float vec2<float>::length() const;
template<> inline double vec2<double>::length() const;
然后在我的 .cpp 文件中实现了它。这工作正常,但它只能 return 相同的模板类型,它不能 return 一个 float length
一个 vec2<int>
。有办法吗?
您可以编写一个辅助类型,在给定向量组件类型的情况下为 length
提供 return 类型。
template<typename T>
struct vec_length_t {};
// Specializations:
template<>
struct vec_length_t<int> { using type = float; };
template<>
struct vec_length_t<float> { using type = float; };
template<>
struct vec_length_t<double> { using type = double; };
(或给它起一个更通用的名称以便在其他地方重复使用,例如 floatify
或类似名称)
然后像这样使用它:
template<typename Number>
struct vec2 {
...
typename vec_length_t<Number>::type length() const;
...
};
要重复用于多个函数或在同一个 class 中使用,您当然也可以使用本地类型别名:
template<typename Number>
struct vec2 {
...
using length_t = typename vec_length_t<Number>::type;
...
length_t length() const;
...
};
这使得在函数体中使用 length_t
来调用正确的 std::sqrt
重载变得很容易(你可能不想使用 double
重载即将 return 一 float
!):
template<typename Number>
vec2<Number>::length_t vec2<Number>::length() const {
// Note that x*x+y*y is a Number, but we want a length_t:
return std::sqrt(static_cast<length_t>(x*x + y*y));
// Or, if you have lengthSquared() defined as returning a Number:
return std::sqrt(static_cast<length_t>(lengthSquared()));
}
有几种可能的选择:
1) 使用某种形式的辅助特征模板为长度提供 return 类型:
如果只提供了你想在模板中存储的类型的特化(int、float、double),那么你可以去掉static_assert(尽管静态断言最在潜在错误消息的可读性方面可能有优势)
一个人还可以只为 int 提供此特征模板的专业化,并为其他所有内容提供通用版本,结合 static_assert 已经存在的工作方式相同,但少了两个专业化写,但在我看来,关于你的 class 处理的类型的知识将分布在两个地方(特征和静态断言)
2) 如果 'general' 情况(double 和 float)的实现是相同的,只有 int 情况不同 - 也可以使 public 长度调用私有长度重载 false_type/true_type 结果为 is_same :),可扩展性较差但不需要任何外部类型:
auto length() -> decltype(length(is_same<T, int>) { return length(is_same<T, int>); }
Number length(std::false_type) { .... }
float length(std::true_type) {....}
当然,使用 C++14 可以摆脱 decltype mambo-jambo。