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;
};
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;
};
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.