Home > Net >  How to use dependent template default parameter with member accesses
How to use dependent template default parameter with member accesses

Time:09-17

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 floats 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;
};
  • Related