设置带有布尔值的比特集的最佳方法
best way to set a bitset with boolean values
假设我有3个 bool
类型值
bool canwalk=true;
bool cantalk=false;
bool caneat=false;
我想设置一个表示三个
的bitset
std::bitset<3> foo;
如何使用布尔值构建bitset
?我想做这样的事情
std::bitset<3> foo(canWalk,cantalk,caneat); //giving me 100
遵循Shivendra agarwal的示例,但是使用接收unsigned long long
的构造器,我提出了以下variadic模板函数(更通用)
template <typename ... Args>
unsigned long long getULL (Args ... as)
{
using unused = int[];
unsigned long long ret { 0ULL };
(void) unused { 0, (ret <<= 1, ret |= (as ? 1ULL : 0ULL), 0)... };
return ret;
}
允许foo
的初始化如下
std::bitset<3> foo{ getULL(canwalk, cantalk, caneat) };
仅当std::bitset
的尺寸不是unsigned long long
中的位数(使用3
肯定是安全的)。
以下是一个完整的工作示例
#include <bitset>
#include <iostream>
template <typename ... Args>
unsigned long long getULL (Args ... as)
{
using unused = int[];
unsigned long long ret { 0ULL };
(void) unused { 0, (ret <<= 1, ret |= (as ? 1ULL : 0ULL), 0)... };
return ret;
}
int main()
{
bool canwalk=true;
bool cantalk=false;
bool caneat=false;
std::bitset<3> foo{ getULL(canwalk, cantalk, caneat) };
std::cout << foo << std::endl;
}
imho,类型的初始化
std::bitset<3> foo(canWalk, cantalk, caneat);
是危险的(容易出错),因为要求std::bitset
的模板参数(示例中的3
)与初始化的参数数相对应。
我提出了" make"函数的创建(遵循std::pair()
,std::tuple()
,std::make_unique()
,std::make_shared
的合并示例,其中的类型和参数数量修复了返回的类型。
所以我提出了以下makeBitSet()
函数,该功能返回 std::bitset<N>
,其中 N
是参数的数字
template <typename ... Args>
std::bitset<sizeof...(Args)> makeBitSet (Args ... as)
{
using unused = bool[];
std::bitset<sizeof...(Args)> ret;
std::size_t ui { ret.size() };
(void) unused { true, (ret.set(--ui, as), true)... };
return ret;
}
该函数可以如下使用
std::bitset<3> foo{ makeBitSet(canwalk, cantalk, caneat) };
,但(更好,恕我直言),使用C 11 auto
,
auto foo = makeBitSet(canwalk, cantalk, caneat);
观察,从C 14开始,makeBitSet()
可以使用返回的auto
型
template <typename ... Args>
auto makeBitSet (Args ... as)
{
// ...
避免烦人的std::bitset<sizeof...(Args)>
冗余。
此外,从C 17开始,您可以使用模板折叠,然后丢弃unused
阵列(以及相应的using
声明),makeBitSet()
可以简化为[编辑:修改:改善性能,遵循建议,来自Mooing Duck(谢谢!)]
template <typename ... Args>
auto makeBitSet (Args ... as)
{
std::bitset<sizeof...(Args)> ret;
std::size_t ui { ret.size() };
( ret.set(--ui, as), ... );
return ret;
}
以下是完整的工作C 11示例
#include <bitset>
#include <iostream>
template <typename ... Args>
std::bitset<sizeof...(Args)> makeBitSet (Args ... as)
{
using unused = bool[];
std::bitset<sizeof...(Args)> ret;
std::size_t ui { ret.size() };
(void) unused { true, (ret.set(--ui, as), true)... };
return ret;
}
int main()
{
bool canwalk { true };
bool cantalk { false };
bool caneat { false };
auto foo = makeBitSet(canwalk, cantalk, caneat);
std::cout << foo << std::endl;
}
引入一个新的API,可以为您提供bitset在参数中接受的字符串输入。
要更通用,建议使用bool数组或 [std::vector<bool>][1]
在getTring()
inline std::string getString(bool canwalk, bool canTalk, bool canEat)
{
std::stringstream input;
str << canwalk?1:0 << cantalk?1:0 << caneat?1:0;
return input.str();
}
现在可以将bitset定义为:
std::bitset<3> foo (getString(canwalk, canTalk, canEat));
您基本上需要一个构建器,该构建器将从布尔设置中构建一个初始值,以传递给std :: bitset的构造函数。您可以在编译时间(而不是运行时)通过variadic模板进行此操作,例如:
template <unsigned long long initialValue>
constexpr unsigned long long bitset_value_builder_impl() { return initialValue; }
template <unsigned long long initialValue, typename First, typename ... Args>
constexpr unsigned long long bitset_value_builder_impl(First &&first, Args &&...args) {
return first ?
bitset_value_builder_impl< (initialValue | (1UL<<sizeof...(args)) ), Args...>(std::forward<Args>(args)...) :
bitset_value_builder_impl< (initialValue & ~(1UL<<sizeof...(args)) ), Args...>(std::forward<Args>(args)...);
}
template <typename First, typename ... Args>
constexpr unsigned long long bitset_value_builder(First &&first, Args &&...args) {
return bitset_value_builder_impl<0, First, Args...>(std::forward<First>(first), std::forward<Args>(args)...);
}
int main()
{
bool canwalk=true;
bool cantalk=false;
bool caneat=false;
std::bitset<3> bits{bitset_value_builder(canwalk, cantalk, caneat)};
std::cout << bits << std::endl; //100
}
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 在C++中向零方向近似的最佳方法
- 使用不同的CRT将新的C++代码与旧的(二进制)组件隔离开来的最佳方法是什么
- 检测win32服务创建和删除的最佳方法
- 在C++中样板"冷/never_inline"错误处理技术的最佳方法是什么?
- 在 c++ 中对类中的 c 字符串动态数组进行排序的最佳方法是什么?
- 将线程中的数据存储到全局容器的最佳方法?
- 将一系列整数放入类的最佳方法是什么?
- 在派生类中使用基类的私有成员变量的最佳方法
- 在 C++ 中将非指定类型作为参数传递的最佳方法?
- Qt - QVector 和模型视图 - 从列表视图获取自定义类的最佳方法是什么?
- 使用 Git 处理 C++ Visual Studio 2019 解决方案的外部依赖项源代码管理的最佳方法是什么?
- 比较两个节点坐标的最佳方法是什么?
- 在nodejs中使用本机代码的最佳方法是什么?
- 将 pybind11 绑定标记为已弃用的最佳方法
- C++:将向量传递到构造函数以创建成员变量的最佳方法?
- C++中变量混叠的最佳方法
- 读取大文件(>2GB)(文本文件包含以太网数据)并通过不同参数随机访问数据的最佳方法是什么?