为一组类型专门化许多模板
Specialize Many Templates for a Set of Types
如何为各种标量值特化多个模板? (例如 int
、float
、size_t
、uint32_t
和 stdint
header 中定义的类型)?
我可以避免为每种类型专门化每个模板吗?
如果可能,我不想使用 boost 或其他 non-standard 库。
template specialization for a set of types有一些解决方案:
用多个功能替换每个模板。每种标量类型一个函数。 (但是有很多模板,那就意味着要写很多函数。)
如果模板采用 non-scalar 类型则失败。 (但我也想为数组类型编写模板。这意味着我需要更改函数的名称。一组用于 scalar-scalar 计算的函数名称。另一组用于 scalar-matrix 计算。还有一个设置为 matrix-matrix 计算。如果我试图重载运算符,我想这不会起作用。)
Nawaz 的元编程解决方案。与本例解决方案 2 中的问题相同。
为每个标量类型专门化一个通用模板。例如,写inline long getRatio<long>
、inline long getRatio<float>
等。可以工作,但需要为许多模板这样做。
再次感谢。
例子
(这使用 Andrew 的解决方案。适用于旧的 std 库。仍然需要 c++11。使用 intel icc -std=c++11 编译):
#define STD_POORMAN stdpoor
namespace stdpoor{
template<bool B, class T = void>
struct enable_if_t {};
template<class T>
struct enable_if_t<true, T> { typedef T type; };
template<class T, T v>
struct integral_constant {
static constexpr T value = v;
typedef T value_type;
typedef integral_constant type;
constexpr operator value_type() const {
noexcept return value;
}
constexpr value_type operator()() const {
noexcept return value;
}
};
typedef integral_constant<bool,true> true_type;
typedef integral_constant<bool,false> false_type;
}
template <typename T>
class SimpleArray;
template <typename T>
struct is_ndscalar : STD_POORMAN::false_type {};
// Specialisations for supported scalar types:
template <> struct is_ndscalar<int> : STD_POORMAN::true_type {};
template <> struct is_ndscalar<float> : STD_POORMAN::true_type {};
template <> struct is_ndscalar<double> : STD_POORMAN::true_type {};
template <> struct is_ndscalar<long> : STD_POORMAN::true_type {};
template <> struct is_ndscalar<long long> : STD_POORMAN::true_type {};
template <typename T>
class SimpleArray{
public:
T* ar_data; //pointer to data
int size; //#elements in the array
SimpleArray(T* in_ar_data, int in_size){
ar_data = in_ar_data;
size = in_size;
};
template <typename T>
void operator+=(const SimpleArray<T>& B){
//array-array +=
int i;
for(i = 0; i < size; ++i){
ar_data[i] += B.ar_data[i];
}
}
template <typename T>
STD_POORMAN::enable_if_t<is_ndscalar<T>::value, void>
operator+=(const T b){
//array-scalar +=
int i;
for(i = 0; i < size; ++i){
ar_data[i] += b;
}
}
};
int main(void){
int base_array[10];
SimpleArray<int> A(base_array, 10);
A += A;
A += 3;
}
如果您尝试仅为某些类型实现此模板,您可以在 .cpp 文件中声明它们,类似于:Why can templates only be implemented in the header file?
如果您希望在此模板中允许任何内容,但明确声明某些类型,此 link 可能会有所帮助:http://en.cppreference.com/w/cpp/language/template_specialization
根据对问题的评论中的讨论,将其浓缩为一个较小的示例,您有一个类型 Matrix<T>
并且您希望实现,比如说 operator+=
。此运算符的行为因操作数是标量还是其他矩阵而异。
您因此想要提供两个专业;一种用于矩阵标量运算,一种用于矩阵-矩阵运算。其中,您想要接受任何有效的标量类型或任何有效的矩阵类型。
这是 type traits and SFINAE using std::enable_if
的经典用例。定义特征 is_scalar
:
// Base template:
template <typename T>
struct is_scalar : std::false_type {};
// Specialisations for supported scalar types:
template <> struct is_scalar<int> : std::true_type {};
template <> struct is_scalar<float> : std::true_type {};
template <> struct is_scalar<double> : std::true_type {};
// etc.
还有一个特质is_matrix
:
// Base template:
template <typename T>
struct is_matrix : std::false_type {};
// Specialisations:
template<typename T>
struct is_matrix<Matrix<T>> : std::true_type {};
// and possibly others...
您的运算符将成为以下形式的(成员)函数模板:
template <typename T>
std::enable_if_t<is_scalar<T>::value, Matrix&> operator+=(const T& rhs) {
// Implementation for addition of scalar to matrix
}
template <typename T>
std::enable_if_t<is_matrix<T>::value, Matrix&> operator+=(const T& rhs) {
// Implementation for addition of matrix to matrix
}
请注意,标准库已经为您提供了 is_scalar
!剩下的就是为您支持的任何矩阵类型定义 is_matrix
特化。
如何为各种标量值特化多个模板? (例如 int
、float
、size_t
、uint32_t
和 stdint
header 中定义的类型)?
我可以避免为每种类型专门化每个模板吗? 如果可能,我不想使用 boost 或其他 non-standard 库。
template specialization for a set of types有一些解决方案:
用多个功能替换每个模板。每种标量类型一个函数。 (但是有很多模板,那就意味着要写很多函数。)
如果模板采用 non-scalar 类型则失败。 (但我也想为数组类型编写模板。这意味着我需要更改函数的名称。一组用于 scalar-scalar 计算的函数名称。另一组用于 scalar-matrix 计算。还有一个设置为 matrix-matrix 计算。如果我试图重载运算符,我想这不会起作用。)
Nawaz 的元编程解决方案。与本例解决方案 2 中的问题相同。
为每个标量类型专门化一个通用模板。例如,写
inline long getRatio<long>
、inline long getRatio<float>
等。可以工作,但需要为许多模板这样做。
再次感谢。
例子 (这使用 Andrew 的解决方案。适用于旧的 std 库。仍然需要 c++11。使用 intel icc -std=c++11 编译):
#define STD_POORMAN stdpoor
namespace stdpoor{
template<bool B, class T = void>
struct enable_if_t {};
template<class T>
struct enable_if_t<true, T> { typedef T type; };
template<class T, T v>
struct integral_constant {
static constexpr T value = v;
typedef T value_type;
typedef integral_constant type;
constexpr operator value_type() const {
noexcept return value;
}
constexpr value_type operator()() const {
noexcept return value;
}
};
typedef integral_constant<bool,true> true_type;
typedef integral_constant<bool,false> false_type;
}
template <typename T>
class SimpleArray;
template <typename T>
struct is_ndscalar : STD_POORMAN::false_type {};
// Specialisations for supported scalar types:
template <> struct is_ndscalar<int> : STD_POORMAN::true_type {};
template <> struct is_ndscalar<float> : STD_POORMAN::true_type {};
template <> struct is_ndscalar<double> : STD_POORMAN::true_type {};
template <> struct is_ndscalar<long> : STD_POORMAN::true_type {};
template <> struct is_ndscalar<long long> : STD_POORMAN::true_type {};
template <typename T>
class SimpleArray{
public:
T* ar_data; //pointer to data
int size; //#elements in the array
SimpleArray(T* in_ar_data, int in_size){
ar_data = in_ar_data;
size = in_size;
};
template <typename T>
void operator+=(const SimpleArray<T>& B){
//array-array +=
int i;
for(i = 0; i < size; ++i){
ar_data[i] += B.ar_data[i];
}
}
template <typename T>
STD_POORMAN::enable_if_t<is_ndscalar<T>::value, void>
operator+=(const T b){
//array-scalar +=
int i;
for(i = 0; i < size; ++i){
ar_data[i] += b;
}
}
};
int main(void){
int base_array[10];
SimpleArray<int> A(base_array, 10);
A += A;
A += 3;
}
如果您尝试仅为某些类型实现此模板,您可以在 .cpp 文件中声明它们,类似于:Why can templates only be implemented in the header file?
如果您希望在此模板中允许任何内容,但明确声明某些类型,此 link 可能会有所帮助:http://en.cppreference.com/w/cpp/language/template_specialization
根据对问题的评论中的讨论,将其浓缩为一个较小的示例,您有一个类型 Matrix<T>
并且您希望实现,比如说 operator+=
。此运算符的行为因操作数是标量还是其他矩阵而异。
您因此想要提供两个专业;一种用于矩阵标量运算,一种用于矩阵-矩阵运算。其中,您想要接受任何有效的标量类型或任何有效的矩阵类型。
这是 type traits and SFINAE using std::enable_if
的经典用例。定义特征 is_scalar
:
// Base template:
template <typename T>
struct is_scalar : std::false_type {};
// Specialisations for supported scalar types:
template <> struct is_scalar<int> : std::true_type {};
template <> struct is_scalar<float> : std::true_type {};
template <> struct is_scalar<double> : std::true_type {};
// etc.
还有一个特质is_matrix
:
// Base template:
template <typename T>
struct is_matrix : std::false_type {};
// Specialisations:
template<typename T>
struct is_matrix<Matrix<T>> : std::true_type {};
// and possibly others...
您的运算符将成为以下形式的(成员)函数模板:
template <typename T>
std::enable_if_t<is_scalar<T>::value, Matrix&> operator+=(const T& rhs) {
// Implementation for addition of scalar to matrix
}
template <typename T>
std::enable_if_t<is_matrix<T>::value, Matrix&> operator+=(const T& rhs) {
// Implementation for addition of matrix to matrix
}
请注意,标准库已经为您提供了 is_scalar
!剩下的就是为您支持的任何矩阵类型定义 is_matrix
特化。