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;
}
Condensing this down to a smaller example, based on the discussion in the comments on the question, you have a type
Matrix<T>
and you wish to implement, say,operator+=
. The behaviour of this operator differs depending on whether the operand is a scalar or another matrix.You therefore want to provide two specialisations; one for matrix-scalar operations, and one for matrix-matrix operations. Within those, you want to accept any valid scalar type, or any valid matrix type.
This is a classic use case for type traits and SFINAE using
std::enable_if
. Define a traitis_scalar
:And a trait
is_matrix
:Your operators will then be (member) function templates of the form:
Note that
is_scalar
is already provided for you by the standard library! All this leaves is for you to defineis_matrix
specialisations for any matrix types you support.If you're trying to implement this template only for certain types you can declare them in a .cpp file, similar to this: Why can templates only be implemented in the header file?
If you want to allow anything to be in this template, but explicitly declare certain types, this link might be helpful: http://en.cppreference.com/w/cpp/language/template_specialization