我有一个模板化类,其数据成员类型为std::vector<T>
,其中T也是模板化类的参数。
在我的模板类中,我有很多逻辑可以做到这一点:
T &value = m_vector[index];
当T是布尔值时,似乎没有编译,因为std :: vector的[]运算符不返回bool-reference,而是返回不同的类型。
一些替代品(虽然我不喜欢其中任何一种):
有没有办法告诉std :: vector不要专门用于bool?
答案 0 :(得分:8)
如果您的数据由T
表示,那么bool
等于std::vector<bool>
,您根本无法定期模板化代码,因为这不是容器。正如@Mark Ransom所指出的,您可以使用std::vector<char>
代替,例如通过像这样的特质
template<typename T> struct vector_trait { typedef std::vector<T> type; };
template<> struct vector_trait<bool> { typedef std::vector<char> type; };
,然后在当前使用typename vector_trait<T>::type
的任何地方使用std::vector<T>
。这里的缺点是您需要使用强制转换从char
转换为bool
。
您自己的答案中建议的替代方法是编写具有隐式转换和构造函数
的包装器template<typename T>
class wrapper
{
public:
wrapper() : value_(T()) {}
/* explicit */ wrapper(T const& t): value_(t) {}
/* explicit */ operator T() { return value_; }
private:
T value_;
};
并在任何地方使用std::vector< wrapper<bool> >
而无需投射。但是,这也有缺点,因为包含真实bool
参数的标准转换序列的行为与用wrapper<bool>
的用户定义转换不同(编译器最多可以使用1个用户定义的转换,并且必要时进行标准转换)。这意味着具有函数重载的模板代码可以巧妙地中断。您可以取消注释上面代码中的explicit
关键字,但会再次引入详细信息。
答案 1 :(得分:4)
改为使用std::vector<char>
。
答案 2 :(得分:4)
以下是否适合您?
template <typename T>
struct anything_but_bool {
typedef T type;
};
template <>
struct anything_but_bool<bool> {
typedef char type;
};
template <typename T>
class your_class {
std::vector<typename anything_but_bool<T>::type> member;
};
不那么轻率,名称anything_but_bool
应该是prevent_bool
或类似。
答案 3 :(得分:1)
有一种方法可以阻止vector<bool>
专业化:传递自定义分配器。
std::vector<bool, myallocator> realbool;
以下文章有一些细节: https://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=98
当然,这要求您可以控制vector
定义,因此它可能不适合您。除此之外,它还有一些缺点......
答案 4 :(得分:1)
您可以使用自定义代理类来保存bools。
class Bool
{
public:
Bool() = default;
Bool(bool in) : value(in) {}
Bool& operator=(bool in) {value = in;}
operator bool() const& {return value;}
private:
bool value;
};
这可能需要为您的目的进行一些调整,但这通常是我在这些情况下所做的。
答案 5 :(得分:1)
我根据您的所有输入找到了更优雅的解决方案。
首先,我定义一个包含一个成员的简单类。我们称之为wrapperClass
:
template <typename T>
class wrapperClass
{
public:
wrapperClass() {}
wrapperClass(const T&value) : m_value(value) {}
T m_value;
};
现在我可以在我的模板化类中定义我的std :: vector,如下所示:
std::vector<wrapperClass<T>> m_internalVector;
由于sizeof(WrapperClass<bool>)
也是1,我希望sizeof(WrapperClass<T>)
始终等于sizeof(T)
。由于数据类型现在不再是bool,因此不执行特化。
在我现在从向量中获取元素的地方,我只需要替换
m_internalVector[index]
通过
m_internalVector[index].m_value
但这似乎比使用traits替换bool更加优雅,然后使用强制转换来转换char和bool(并且可能重新解释转换以将char&amp;转换为bool&amp;)。
您怎么看?