如何防止性病::载体<bool>的专业化
How to prevent specialization of std::vector<bool>
我有一个模板化类,它有一个类型为std::vector<T>
的数据成员,其中T也是我的模板化类的参数。
在我的模板类中,我有一些逻辑可以做到这一点:
T &value = m_vector[index];
当t是布尔值时,这似乎不会编译,因为std::vector的[]运算符不返回布尔引用,而是返回不同的类型。
一些替代方案(尽管我不喜欢其中任何一个(:
- 告诉我的用户,他们不能使用bool作为模板参数
- 让我的类专门用于bool(但这需要一些代码重复(
难道没有办法告诉std::vector不要专门针对bool吗?
如果数据由std::vector<bool>
表示,那么模板化代码就不能使T
与bool
有规律地运行,因为CCD_4不是容器。正如@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; };
然后在当前使用std::vector<T>
的任何位置使用typename vector_trait<T>::type
。这里的缺点是需要使用强制转换来从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_;
};
并且在任何地方都使用CCD_ 10而不必进行投射。然而,这也有缺点,因为包含真实bool
参数的标准转换序列的行为与使用wrapper<bool>
的用户定义转换不同(编译器最多可以使用1个用户定义转换,并根据需要使用尽可能多的标准转换(。这意味着带有函数重载的模板代码可能会微妙地中断。您可以在上面的代码中取消注释explicit
关键字,但这再次引入了冗长性。
请改用std::vector<char>
。
以下内容适合您吗?
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
或类似的名称。
基于您的所有输入,我找到了一个更优雅的解决方案。
首先,我定义了一个包含一个成员的简单类。让我们称之为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)
。由于数据类型现在不再是布尔,因此不执行专门化。
在我现在从向量中获得元素的地方,我只需替换
m_internalVector[index]
通过
m_internalVector[index].m_value
但这似乎比使用traits将bool替换为char,然后使用强制转换在char和bool之间转换(可能还会重新解释强制转换以将char&转换为bool&(要优雅得多。
你觉得怎么样?
您可以使用自定义代理类来保存布尔。
class Bool
{
public:
Bool() = default;
Bool(bool in) : value(in) {}
Bool& operator=(bool in) {value = in;}
operator bool() const& {return value;}
private:
bool value;
};
出于您的目的,这可能需要进行一些调整,但在这种情况下,我通常会这样做。
std::basic_string<bool> flags(flagCount, false);
从语义上讲,使用string
很奇怪,但它的工作原理基本上与std::vector
类似,使用指针/引用时的行为与预期一致,并且在传递到占用跨度的函数时,它可以方便地转换为std::span<bool>
,不需要包装类或repret_cast(例如,使用CCD24会因为强制转换而使这些情况变得尴尬(。除非C++添加了一个std::bit_vector
并反对专业化,否则我们没有太多好的选择。
有一种方法可以防止vector<bool>
专门化:传递自定义分配器。
std::vector<bool, myallocator> realbool;
以下文章提供了一些详细信息:https://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=98
当然,这需要您能够控制vector
定义,所以它可能不是真正适合您的解决方案。除此之外,它本身也有一些缺点。。。
- 写入向量<向量<bool>>
- EASTL矢量<向量<int>>连续的
- 让bool方法返回其他整数
- 如何在 std::vector 中找到<bool>哪些索引是真的?
- Arduino-C++ bool 不会从 false 变为 true
- 为什么在这种情况下,bool 类型的输出等于 0?
- 显式 std::exception_ptr 转换为 bool 不存在.VS2010 错误?
- 错误:不能使用"显式"说明符声明 bool'
- 为什么 C++ 11 在 ios 类中添加了运算符 bool
- 从标准::字符串到标准::矢量<bool>的快速转换
- 为什么 bool 和 _Bool 如果它们在内存中占用 1 个字节,它们只能存储 0 或 1
- 通过 mpi 发送 c++ 标准::矢量<bool>
- 为什么使用Pool和Bool而不是int8_t或char
- 如何为地图< map<int,int> 、bool > 分配值?
- 为什么更改包含 psapi.h 的顺序会产生编译错误?(标识符 BOOL 未定义)
- 使用 bool 和 const char 重载的 C++ 函数会在没有警告的情况下产生歧义 (MSVC2012)
- 返回 bool 作为 CPP 中 bool 运算符 [] 中的值
- 如何告诉自动推断向量<bool>元素的非引用类型
- 当 Type = bool 时,运算符 bool() 与模板 Type() 运算符冲突
- 为什么"std::set::erase(const key_type&)"返回"size_type"而不是"bool"?