Home > other >  Initialze a member of a C templated class only for specific type
Initialze a member of a C templated class only for specific type

Time:05-26

Suppose I have a templated class like this:

template <typename C>
class ValArray
{
    ValArray() = default;
    ValArray(const ValArray&) = delete;

    C& operator[](size_t pos) { return _values[pos]; }
  ...
private:
    std::array<C, ARRAY_SIZE> _values;
};

This is instantiated with lots of different types. What I would like to do is initialize _values only for type bool but not for other types. So, if I create ValArray<bool> val then I want all elements to be false, for example:

std::array<bool, ARRAY_SIZE> _values = {false};

But for any other type, I don't want to initialize _values at all.

Is there some template magic I haven't been able to find that will allow this? I'm hoping to not have to create a separate class for this, as this would cascade to many other places where I'd have to create specializations.

CodePudding user response:

In C 17 and later, you can use if constexpr inside the constructor to assign the array elements, eg:

template <typename C>
class ValArray
{
public:
    ValArray() {
        if constexpr (std::is_same_v<C, bool>) {
            _values.fill(false);
        }
    }

    ...

private:
    std::array<C, ARRAY_SIZE> _values;
};

Online Demo

If C is bool, the constructor will be compiled as:

ValArray() { _values.fill(false); }

Otherwise it will be compiled as:

ValArray() {}

Prior to C 17, you can accomplish the same thing using SFINAE via std::enable_if, eg:

template <typename C>
class ValArray
{
public:
    template<typename T = C, typename std::enable_if<std::is_same<T, bool>::value, int>::type = 0>
    ValArray() { _values.fill(false); }

    template<typename T = C, typename std::enable_if<!std::is_same<T, bool>::value, int>::type = 0>
    ValArray() { }
    
    // ...

private:
    std::array<C, ARRAY_SIZE> _values;
};

Online Demo

CodePudding user response:

Among ways HOW this can be done you can simply add a specialization for a class member after declaration you already have for this case, something like this:

template<> 
constexpr ValArray<bool>::ValArray() noexcept : _values({}) {};

Similar constructs for specialization are avialable in very early version of C , no SFINAE or if constexpr is required in this case.

  • Related