为一组类型专门化多个模板
Specialize Many Templates for a Set of Types
如何专门化各种标量值的许多模板?(如int
, float
, size_t
, uint32_t
,以及stdint
头中定义的类型)?
我可以避免为每个类型对每个模板进行专门化吗?如果可能的话,我不想使用boost或其他非标准库。
对于一组类型的模板专门化有一些解决方案:
-
将每个模板替换为多个函数。每个标量类型对应一个函数。(但有很多模板。
-
如果模板采用非标量类型,则失败。(但我也想为数组类型编写模板。这意味着我需要更改函数的名称。一组用于标量-标量计算的函数名。另一个用于标量矩阵计算的集合。又是一个矩阵-矩阵计算的集合。如果我试图重载操作符,我猜这不会工作。)
-
Nawaz的元编程解决方案。
-
为每个标量类型专门化一个泛型模板。例如,写
inline long getRatio<long>
,inline long getRatio<float>
等。可以工作,但需要为许多模板这样做
再次感谢。
的例子(这里使用了安德鲁的解决方案。改编为旧的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;
}
将其浓缩为一个较小的示例,基于对该问题的评论中的讨论,您有一个类型Matrix<T>
,并且您希望实现,例如operator+=
。该操作符的行为取决于操作数是标量还是另一个矩阵。
这是使用std::enable_if
的类型特征和SFINAE的经典用例。定义一个trait 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
专门化。
如果您只想为某些类型实现此模板,您可以在.cpp文件中声明它们,类似于:为什么模板只能在头文件中实现?
如果你想在这个模板中允许任何东西,但明确声明某些类型,这个链接可能会有帮助:http://en.cppreference.com/w/cpp/language/template_specialization
- 线程 std::调用未知类型,无法专门化函数错误
- 如何为所有非数组类型专门化模板?
- 如何在同一个模板功能上专门化几种类型?
- 如何为底层类型 int 的枚举专门化类
- 扣除指南的尾随回报类型不是专门化
- C++模板方法专门化联合类型
- 专门化模板数据类型的模板
- 无法专门化 std::hash 以unordered_map存储自定义类型
- 使用非类型模板参数进行专门化模板模板参数
- g++和clang++在结构/类专门化中具有非类型参数的不同行为
- C++模板专门化除一种类型外的所有类型
- 基于类型特征专门化强制转换运算符
- 使用decltype尾部返回类型专门化函数模板
- 可以转发声明的类型模板参与模板专门化
- 专门化泛型类型的函数组
- 错误:T没有命名类型-用于使用强类型枚举的专门化
- 模板类在模板类型之间转换,但也专门化
- 是否可以为模板化类型专门化模板
- 如何在任意依赖类型上专门化模板
- 如何根据模板参数是否具有别名来专门化类型