【发布时间】:2017-01-17 19:48:19
【问题描述】:
如何为各种标量值专门化许多模板? (如int、float、size_t、uint32_t,以及stdint标头中定义的类型)?
我可以避免为每种类型专门设置每个模板吗? 如果可能,我不想使用 boost 或其他非标准库。
template specialization for a set of types有一些解决方案:
用多个函数替换每个模板。每个标量类型一个函数。 (但是有很多模板。那就意味着要编写很多函数。)
如果模板采用非标量类型,则失败。 (但我也想为数组类型编写模板。这意味着我需要更改函数的名称。一组用于标量-标量计算的函数名。另一组用于标量-矩阵计算。另一组用于矩阵-矩阵计算。如果我试图重载运算符,我想这将不起作用。)
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;
}
【问题讨论】:
-
您要解决的具体问题是什么?这是非常广泛的。
-
我同意 Barry 的要求,要求提供更窄的问题陈述。目前尚不清楚您是否想简单地允许将多个模板用于您确定为“标量类型”的任何东西,SFINAE 和适当的特征就足够了,或者您是否需要这些特化来包含 @987654330 的不同代码@ 与
float相比(例如)。一个具体的例子可能会产生更有针对性的建议。 -
写一个数组操作的小库,类似于python的numpy库。此时,我想将每个模板专门化为标量类型的计算(例如运算符 *=、+= 等),并且还能够专门化所有矩阵类型的模板(int 矩阵、float 矩阵等)。
-
我明白了。那我再举个例子吧。
-
您的意思是“专业化”还是“启用”?专业化意味着您期望
float与int相比有不同的实现,例如operator+=。启用仅仅意味着您允许float或int(或任何其他标识的“标量类型”)实例化,但不允许Matrix或std::string(或任何未标识为“标量类型”的东西)实例化。听起来这就是您想要的,但希望该示例将进一步提高清晰度。
标签: c++ templates template-specialization