I have a templated class that has a data member of type std::vector<T>
, where T is also a parameter of my templated class.
In my template class I have quite some logic that does this:
T &value = m_vector[index];
This doesn't seem to compile when T is a boolean, because the [] operator of std::vector does not return a bool-reference, but a different type.
Some alternatives (although I don't like any of them):
Isn't there a way to tell std::vector not to specialize for bool?
You simply cannot have templated code behave regularly for T
equal to bool
if your data is represented by std::vector<bool>
because this is not a container. As pointed out by @Mark Ransom, you could use std::vector<char>
instead, e.g. through a trait like this
template<typename T> struct vector_trait { typedef std::vector<T> type; };
template<> struct vector_trait<bool> { typedef std::vector<char> type; };
and then use typename vector_trait<T>::type
wherever you currently use std::vector<T>
. The disadvantage here is that you need to use casts to convert from char
to bool
.
An alternative as suggested in your own answer is to write a wrapper with implicit conversion and constructor
template<typename T>
class wrapper
{
public:
wrapper() : value_(T()) {}
/* explicit */ wrapper(T const& t): value_(t) {}
/* explicit */ operator T() { return value_; }
private:
T value_;
};
and use std::vector< wrapper<bool> >
everywhere without ever having to cast. However, there are also disadvantages to this because standard conversion sequences containing real bool
parameters behave differently than the user-defined conversions with wrapper<bool>
(the compiler can at most use 1 user-defined conversion, and as many standard conversions as necessary). This means that template code with function overloading can subtly break. You could uncomment the explicit
keywords in the code above but that introduces the verbosity again.