How to specialize many template for all kinds of scalar values? (such as int
, float
, size_t
, uint32_t
, and types defined in the stdint
header)?
Can I avoid specializing each template for each of the types? I don't want to use boost or other non-standard libraries if possible.
There are some solutions at template specialization for a set of types:
Replace each template with multiple functions. One function for each scalar type. (But there are many templates. That would mean writing many functions.)
Fail if the template takes a non-scalar type. (But I also want to write template for array types. This would mean I need to change the names of the functions. One set of function names for scalar-scalar calculation. Another set for scalar-matrix calculation. Yet another set for matrix-matrix calculation. If I am trying to overload operators, i guess this won't work.)
Metaprogramming solution by Nawaz. Same problem as in solution 2 for this case.
Specialize a generic template for each scalar type. For example, write
inline long getRatio<long>
,inline long getRatio<float>
, etc. Can work, but need to do that for the many templates.
Thanks again.
Example (this uses Andrew's solution. adapted for an old std library. still need c++11. compiled with 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;
}