Specialization of functions in the template class for float and double litals

I am trying to find a solution to have constant numeric literals inside a template class method. I am making some math template classes for use with floating or double types. The problem is that literals differ depending on the data type (for example, “0.5f” for float and “0.5” for double). So far I have come up with two solutions. Some hypothetical code for the first:

template <typename T> class SomeClass { public: T doSomething(T x); }; template <> float SomeClass<float>::doSomething(float x) { float y = 0.5f; /* * Do computations... */ return x; } template <> double SomeClass<double>::doSomething(double x) { double y = 0.5; /* * Do computations... */ return x; } 

The above approach forces you to rewrite entire methods for each type with which it is used.

Another approach:

 template <typename T> class SomeClass { public: T doSomething(T x); private: T getValue(); }; template <typename T> T SomeClass<T>::doSomething(T x) { T y = getValue(); /* * Do computations... */ return x; } template <> float SomeClass<float>::getValue() { return 0.5f; } template <> double SomeClass<double>::getValue() { return 0.5; } 

For this, it is not necessary to write the same methods several times for a certain type, but it requires many getValue () methods for each "magic number" that should be used inside the method.

Is there another, more elegant, way to solve this problem?

+8
c ++ function templates literals specialization
source share
3 answers

Thank you all for your answers and comments. I allowed myself to make a summary of what has been said so far and add my conclusions.

I am going to implement some math class template that will be created for use with float or double. Some numeric literals must be used inside the class. These will be commonly used numeric literals and constants, such as 0.0, 0.5, 1.0, pi, etc. I am looking for a solution to create an instance of a class for different literals depending on its type.

Should float and double be used literals or not?

The discussion is a bit on the topic of whether to use separate literals for float and double. This may be caused by a slightly unfortunate example that I gave in my question. In the example, the literal will in any case be converted to the correct type, so there will be no harm. But in general there will be cases when a literal should be used in an expression, for example:

 float foo(float x) { return x * 3.14; } 

This will force the compiler to convert x to double, perform the calculations, and then convert the result back to float. Pros and cons of this behavior:

Pros:

  • Exact gain, because the actual calculations will be performed in double precision.

Minuses:

  • If performance is a problem, it can lead to faster as well as slower execution, depending on the environment and platform. This introduces some performance changes depending on the implementation, which as far as I think is bad.
  • Introduces inconsistency in the calculations, since some operations will be done on floats, and some on paired ones, depending on the use of literals. This may also open some errors.
  • This violates the idea of ​​class specialization for floats in the first place because internal calculations will be performed by doubling anyway.

In conclusion, the goal is to instantiate the class for the correct types without any additional conversions. The idea of ​​using double type literals around the world, such as 0.5 and leaving the proper conversion processing to the compiler, is not an option.

Related topics: Should we usually use float literals for float instead of simpler double literals?

Possible solutions?

  • Specialize methods for each type of template instance where literals should be used. This is probably the worst solution because it forces you to write the same code twice with minor changes to literals.
  • Make specialized methods getValue<type>() or as Jonathan Wackel published - specialized members. This can lead to some stupid members or methods in the class, such as getZeroPointFive<float>() .
  • Mohammad and Tony Delroy noted that wrapping each literal with static_cast<T>() would do the trick. Converting to the correct type will be at compile time.
+1
source share

You just don't need to worry about this - use 0.5, and if the type is float, the compiler will still initialize it optimally with the same value as if you were using 0.5f.

This is a bit lengthy, but you can read part of the “other mechanisms supporting polymorphism”, part of my answer here: Polymorphism in C ++

For a more general use of the float constant in the entire function, especially in comparison and expressions, it is worth reading the bluemess link below.

0
source share

Assuming that it is actually necessary to use different values ​​in two specializations (for example, it is not necessary, for example, for 0.5 and 0.5f), it would be much less typing:

 template <typename T> class SomeClass { public: T doSomething(T x); private: static const T magic_number_1; }; template <typename T> T SomeClass<T>::doSomething(T x) { T y = magic_number_1; /* * Do computations... */ return x; } template <> const float SomeClass<float>::magic_number_1 = 0.5f; template <> const double SomeClass<double>::magic_number_1 = 0.5; 
0
source share

All Articles