I do not know how to solve a problem which can be illustrated with the following struct
:
template <typename T, unsigned WIDTH=T::width>
struct Handler {
static unsigned const width = WIDTH;
};
There is a struct
(in this case called Handler
) which takes as template parameter a type T
. In the codebase, where this struct
is used, special binary types are used which have a member width
(the number of bits of the type). As this Handler
is supposed to only work with that binary type the second parameter WIDTH
has the default value of T::width
. Note that there is much more code into it but the code above should only provide a short explanation.
Now I want to be able to allow float
s in this Handler
with WIDTH
set to 32
as the default parameter so that I can use Handler<float>
. Apart from the template parameters, the Handler
should work with float
out of the box. Of course, if I directly use Handler<float>
or even Handler<float, 32>
(undesired solution) I get error: ‘width’ is not a member of ‘float’
. So I need the code to be able to use the constant value 32
if T
is float
and T::width
otherwise.
I tried to use ternary operators in the default parameter for WIDTH
with the use of std::is_same
and a special function for calculating the width depending on the provided type. Both attempts also result in the error above.
I also looked into template specialization but then I would also need to specialize WIDTH
which would be needed to be provided (i.e. Handler<float, 32>
) afterwards, wouldn't it?
I would really appreciate some tips/solutions.
CodePudding user response:
You can use a trait helper class to solve this. By default it'll use ::width
but can be specialised for other types:
template<typename T>
struct width_trait
{
static unsigned const width = T::width;
};
template<>
struct width_trait<float>
{
static unsigned const width = 32;
};
template <typename T, unsigned WIDTH=width_trait<T>::width>
struct Handler {
static unsigned const width = WIDTH;
};