使用布尔值设置bitset的最佳方法

时间:2017-12-13 20:36:26

标签: c++ c++11 bitset

假设我有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

4 个答案:

答案 0 :(得分:2)

引入一个新的api,它可以为你提供bitset在参数中接受的字符串输入。

更通用,建议使用bool数组或sudo apt-get install gtk2.0 sudo apt-get install build-essential libgtk2.0-dev 去掉getString()中的这些变量参数

[std::vector<bool>][1]

现在可以将bitset定义为:

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();
}

答案 1 :(得分:2)

以Shivendra Agarwal为例,但使用接收unsigned long long的构造函数,我提出了以下可变参数模板函数(更通用)

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

答案 2 :(得分:1)

您基本上需要一个构建器,它将从您的布尔集构建一个初始值,以传递给std :: bitset的构造函数。您可以通过可变参数模板在编译时(而不是运行时)执行此操作,如下所示:

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
}

答案 3 :(得分:1)

恕我直言,类型

的初始化
std::bitset<3> foo(canWalk, cantalk, caneat);

是危险的(容易出错),因为要求std::bitset(示例中)3的模板参数对应于初始化的参数个数。

我建议创建一个&#34; make&#34; function(遵循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;
 }