I ran across an interesting case where I needed to use
std::remove_const to ensure a template parameter wasn’t const by default. I had something like this:
With the library I was using, TooN 2.0.0 beta8, this resulted in a compile error. The error stated that when the vector returned from
project() was being created, the compiler couldn’t invoke assign to a read only location. A simplified declaration of
project() looks as follows:
project() function returns is not important; what is important is the use of the template parameter
Precision in both the argument type and the return type. When I invoke
operator on a const Matrix object, the returned vector’s precision inherits the const.
When this vector is passed to the
project() function above, the function tries to create and return a
Vector<3, const double> which can only be initialized with a constexpr. Assigning to it via operator= or a constructor will not work to copy the data from the other vector.
There are several ways one can fix this, all of them involving removing the const qualifier from the Precision type on the returned vector.
It may seem like a simple solution would work:
Unfortunately, this requires the function be invoked as
project<Size, Precision, Base, P2>(v); which is undesirable.
The first solution is simple, but tedious if you have several functions with similar signatures:
std::remove_const<T>::type is a type expression equal to the original type
T, but with any const qualifiers removed. In this way,
const double becomes simply
Another solution is to prevent the creation of a Vector object with a const precision, the idea that a non-slice vector with const data isn’t very useful – you can’t even construct one properly. Generally the only time you would actually want a vector with const data is when that data is pointing to some already existing area in memory (a slice).
Consider the following toy code for a vector class:
Vector object is backed by owned storage (
StackBase), the data is declared explicitly to be of a non-const type. Similarly, the return types of
operator are defined to be the const and non-const reference types. The
SliceBase, which handles references to un-owned data, retains the original templated type to allow pointing to constant data.
While this method prevents the creation of Vector objects with const owned data, it also means you don’t have to augment functions that interface with these objects to correct the return type.