Class Template for Numeric Types

Class template for numeric types

You can use the std::is_arithmetic type trait. If you want to only enable instantiation of a class with such a type, use it in conjunction with std::enable_if:

#include <type_traits>

template<
typename T, //real type
typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type
> struct S{};

int main() {
S<int> s; //compiles
S<char*> s; //doesn't compile
}

For a version of enable_if that's easier to use, and a free addition of disable_if, I highly recommend reading this wonderful article on the matter.

In C++, the technique described above has a name called "Substitution Failure Is Not An Error" (most use the acronym SFINAE). You can read more about this C++ technique on wikipedia or cppreference.com.

As of C++20, concepts make this much easier and don't spoil the interface:

#include <concepts>

template<typename T>
concept arithmetic = std::integral<T> or std::floating_point<T>;

template<typename T>
requires arithmetic<T>
struct S{};
// Shorthand: template<arithmetic T> struct S {};

Do note that there are many user types meant to be used arithmetically as well, though, so a more general concept that covers the operations you're looking for instead of the types you're looking for would be preferable in a generic interface.

C++ template for numeric types

There's probably better ways of doing this, but the simplest way to me is to just slap the enable_if onto the return type:

template<typename T, typename ... Types>
typename std::enable_if<
std::is_arithmetic<T>::value
>::type
myFct(T arg1, Types ... rest) { /*do numeric stuff*/ }

template<typename T, typename ... Types>
typename std::enable_if<
!std::is_arithmetic<T>::value
>::type
myFct(T arg1, Types ... rest) { /*do non-numeric stuff*/ }

This gets very unwieldy once you have more than just two mutually exclusive options, but this will definitely work.

Template friendly string to numeric in C++

Why there are no template functions something like:

C++17 has such generic string to number function, but named differently. They went with std::from_chars, which is overloaded for all numeric types.

As you can see, the first overload is taking any integer type as an output parameter and will assign the value to it if possible.

It can be used like this:

template<typename Numeric>
void stuff(std::string_view s) {
auto value = Numeric{};

auto [ptr, error] = std::from_chars(s.data(), s.data() + s.size(), value);

if (error != std::errc{}) {
// error with the conversion
} else {
// conversion successful, do stuff with value
}
}

As you can see, it can work in generic context.

Template Function Specialization for Integer Types

Use SFINAE

// For all types except integral types:
template<typename T>
typename std::enable_if<!std::is_integral<T>::value>::type f(T t)
{
// ...
}

// For integral types only:
template<typename T>
typename std::enable_if<std::is_integral<T>::value>::type f(T t)
{
// ...
}

Note that you will have to include the full std::enable_if return value even for the declaration.

C++17 update:

// For all types except integral types:
template<typename T>
std::enable_if_t<!std::is_integral_v<T>> f(T t)
{
// ...
}

// For integral types only:
template<typename T>
std::enable_if_t<std::is_integral_v<T>> f(T t)
{
// ...
}

C++ Limit template type to numbers

What you need std::is_arithmetic to constrain the template type to a arithmetic types (integral or floating point). You can use it like

template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
void Deposit(T t) {...}

How to wrap a C function library that works with different numeric types into a C++ template class

I'm not sure I've caught exactly the problem.
Something like that using partial specialization could solve?

template<class T>
class Fwd { }

template<>
class Fwd<double> {
void execute(std::pair<double, double> pp) {
fftw_execute(pp);
}
}

template<>
class Fwd<float> {
void execute(std::pair<float, float> pp) {
fftwf_execute(pp);
}
}

// and so on...

How do I refer to a class with multiple template types by only one of the types?

It seems like you are looking for CTAD (class template argument deduction). It only works when the caller does not specify any template argument, hence a layer of indirection has to be added:

template <typename T>
struct ShapeWrap {
template <typename U,typename V>
struct Shape {
T value;
U input;
V input2;
Shape(const U& u,const V& v) : input(u),input2(v) {}
};
};

Caller can now call:

auto s = ShapeWrap<int>::Shape(1.0,0.1f);

To instantiate ShapeWrap<int>::Shape<double,float>.


Alternatively via template argument deduction of a function template:

template <typename T, typename U,typename V>
struct Shape {
T value;
U input;
V input2;
Shape(const U& u,const V& v) : input(u),input2(v) {}
};

template <typename T,typename U,typename V>
Shape<T,U,V> make_shape(const U& u, const V& v) {
return {u,v};
}

int main() {
auto s = make_shape<int>(1.0,0.1f);
}

Partial class template specialisation for multiple types

I suppose you can use a boolean default value, like in foo struct in the following example

#include <iostream>

template <typename>
struct isSpecialType
{ static constexpr bool value { false }; };

template <>
struct isSpecialType<int>
{ static constexpr bool value { true }; };

template <>
struct isSpecialType<double>
{ static constexpr bool value { true }; };

template <typename T, bool = isSpecialType<T>::value>
struct foo;

template <typename T>
struct foo<T, true>
{ static constexpr bool value { true }; };

template <typename T>
struct foo<T, false>
{ static constexpr bool value { false }; };

int main()
{
std::cout << "- void value: " << foo<void>::value << std::endl;
std::cout << "- bool value: " << foo<bool>::value << std::endl;
std::cout << "- int value: " << foo<int>::value << std::endl;
std::cout << "- double value: " << foo<double>::value << std::endl;
}

The idea is define a sort of type traits (isSpecialType) to choose the selected types (int and double, in your example) with a booleand value that is false in the generic implementation and true in the specializations.

template <typename>
struct isSpecialType
{ static constexpr bool value { false }; };

template <>
struct isSpecialType<int>
{ static constexpr bool value { true }; };

template <>
struct isSpecialType<double>
{ static constexpr bool value { true }; };

Next you have to declare the foo struct (class Vec, in your question) with a supplemental bool template value with the isSpecialType<T>::value default value

template <typename T, bool = isSpecialType<T>::value>
struct foo;

Last, you have to implement two partially specialized version of foo: the first one with the boolean true value

template <typename T>
struct foo<T, true>
{ static constexpr bool value { true }; };

corresponding to the specialized version of your Vec; the one with the false boolean value

template <typename T>
struct foo<T, false>
{ static constexpr bool value { false }; };

corresponding to the generic version of your Vec.

Another point: my example is C++11 or newer code; if you want a C++98 version, you have only to define the bool values as const (instead constexpr) and initialize they whit the C++98 style; I mean

 static bool const bool value = true;

instead of

 static constexpr bool value { true };


Related Topics



Leave a reply



Submit