关于bitset
bitset就是可以存放二进制的容器。
对于bitset的主要操作有:
Construct bitset (public member function) //构造bitset.. 格式bitset<长度> 名字
Bitset operators (functions) //可以直接对bitset容器进行二进制操作,如^,|,~,<<,>>等等
Access bit (public member function) //可以用如数组形式的赋值。bitset<4> b; b[0]=1;
Set bits (public member function)//默认将容器中所有值赋为1,也可以将特定的位置赋给特定的值
如 bitset<4> b; b.set(); //1111. b.set(2,0) // 1011.
Reset bits (public member function) //默认将容器中所有值赋值为0,也可以将特定位置赋特定的值
Flip bits (public member function)//默认将容器中的数取反,1变0,0变1,也可以将特定位置取反bitset<4>b(string ("0001")); b.file(2); // 0101; b.file(); //1010
Convert to unsigned longinteger (public member function) //将容器的值转化成10进制的数
Convert to string (public member function) //将容器累的值转为字符串
Count bits set (public member function) //统计容器中1的个数
Return size (public member function) //容器的大小
Return bit value (public member function) //返回每个位置上的数
Test if any bit is set (public member function) //容器的值>0返回真,反之。
Test if no bit is set (public member function) //和any取反。容器的值==0返回真。反之
表3-7 bitset操作
b.any() |
b中是否存在置为1的二进制位? |
b.none() |
b中不存在置为1的二进制位吗? |
b.count() |
b中置为1的二进制位的个数 |
b.size() |
b中二进制位的个数 |
b[pos] |
访问b中在pos处的二进制位 |
b.test(pos) |
b中在pos处的二进制位是否为1? |
b.set() |
把b中所有二进制位都置为1 |
b.set(pos) |
把b中在pos处的二进制位置为1 |
b.reset() |
把b中所有二进制位都置为0 |
b.reset(pos) |
把b中在pos处的二进制位置为0 |
b.flip() |
把b中所有二进制位逐位取反 |
b.flip(pos) |
把b中在pos处的二进制位取反 |
b.to_ulong() |
用b中同样的二进制位返回一个unsigned long值 |
os << b |
把b中的位集输出到os流 |
Urand.h
/** * 书本:【ThinkingInC++】 * 功能:关于模板bitset * 时间:2014年10月16日16:28:59 * 作者:cutter_point */ #ifndef URAND_H_INCLUDED #define URAND_H_INCLUDED #include <bitset> #include <cstddef> #include <cstdlib> #include <ctime> using std::size_t; using std::bitset; template<size_t UpperBound> class Urand { bitset<UpperBound> used; public: Urand() { srand(time(0)); } //产生随机数 size_t operator()(); }; template<size_t UpperBound> inline size_t Urand<UpperBound>::operator()() { if(used.count() == UpperBound)//b.count() b中置为1的二进制位的个数 used.reset(); //说明已经满了,里面为1的个数满了,全为1,那么这个让他全部重置为0 size_t newval; while(used[newval = rand()%UpperBound]) ; //找到唯一的数值,就是为假的时候跳出来 used[newval]=true; return newval; } #endif // URAND_H_INCLUDED
UrandTest.cpp
/** * 书本:【ThinkingInC++】 * 功能:关于如何使用Urand.h * 时间:2014年10月16日16:29:21 * 作者:cutter_point */ #include <iostream> #include "Urand.h" using namespace std; int main() { Urand<10> u; for(int i=0 ; i < 20 ; ++i) cout<<u()<<' '; system("pause"); return 0; }
TempTemp.cpp
/** * 书本:【ThinkingInC++】 * 功能:关于模板类型的模板参数 * 时间:2014年10月16日16:29:58 * 作者:cutter_point */ #include <cstddef> #include <iostream> using namespace std; template<class T> class Array { enum { INIT=10 }; //美剧类型,这是为了避免使用宏 T* data; size_t capacity; size_t count; public: Array() { count=0; data=new T[capacity = INIT]; //创建一个T类型的数组 } ~Array() { delete [] data; } void push_back(const T& t) { if(count == capacity) //如果数量和总的个数一样,说明内存不够 { size_t newCap=2*capacity; //把内存空间增加一倍 T* newData=new T[newCap]; //把原来的数据移动到新的数组上 for(int i=0 ; i<count ; ++i) newData[i]=data[i]; //回收旧的空间 delete []data; //更新数据成员 data=newData; capacity=newCap; } //如果还有空余空间 data[count++]=t; //把t赋值给最后的一个空闲的地方 } void pop_back() { if(count > 0) --count; //把最后一位去掉 } T* begin() { return data; } T* end() { return data+count; } }; template<class T, template<class> class Seq> //这里可以这样写template<class T, template<class U> class Seq> class Container { Seq<T> seq; //参照上面那个模板,这里seq就相当于T public: void append(const T& t) { seq.push_back(t); } T* begin() { return seq.begin(); } T* end() { return seq.end(); } }; int main() { Container<int, Array> container; //template<class T> class Array 这里seq就相当于Array container.append(1); container.append(2); int* p=container.begin(); while(p != container.end()) cout<<*p++<<endl; return 0; }
关于typename的探讨
"typename
"是一个C++程序设计语言中的关键字。当用于泛型编程时是另一术语"class
"的同义词。[1]这个关键字用于指出模板声明(或定义)中的非独立名称(dependent
names)是类型名,而非变量名。以下是对于泛型编程中typename
两种迥然不同的用法的解释。
class
关键字的同义词这是一项C++编程语言的泛型编程(或曰“模板编程”)的功能,typename
关键字用于引入一个模板参数,例如:
// 定义一个返回参数中较大者的通用函数
template <typename T>
const T& max(const T& x, const T& y)
{
if (y < x){
return x;
}
return y;
}
这种情况下,typename
可用另一个等效的关键字class
代替,如下代码片段所示:
// 定义一个返回参数中较大者的通用函数
template <class T>
const T& max(const T& x, const T& y)
{
if (y < x) {
return x;
}
return y;
}
以上两段代码没有功能上的区别。
考虑下面的错误代码:
template <typename T>
void foo(const T& t)
{
// 声明一个指向某个类型为T::bar的对象的指针
T::bar * p;
}
struct StructWithBarAsType {
typedef int bar;
};
int main() {
StructWithBarAsType x;
foo(x);
}
这段代码看起来能通过编译,但是事实上这段代码并不正确。因为编译器并不知道T::bar
究竟是一个类型的名字还是一个某个变量的名字。究其根本,造成这种歧义的原因在于,编译器不明白T::bar
到底是不是“模板参数的非独立名字”,简称“非独立名字”。[2]注意,任何含有名为“bar
”的项的类T,都可以被当作模板参数传入foo()
函数,包括typedef
类型、枚举类型或者变量等。
A name used in a template declaration or definition andthat is dependent on a template-parameter is assumed not to name a type unlessthe applicable name lookup finds a type name or the name is qualified by thekeyword typename.
意即出现上述歧义时,编译器将自动默认bar为一个变量名,而不是类型名。所以上面例子中的代码 T::bar * p
会被解释为乘法,而不是声明p为指向T::bar类型的对象的指针。
如果还有另一个名为StructWithBarAsValue
类型,如下:
struct StructWithBarAsValue {
int bar;
};
那么,编译器将以完全不同的方式来解释
T::bar * p
的含义。
解决问题的最终办法,就是显式地告诉编译器,T::bar
是一个类型名。这就必须用typename
关键字,例如:
template <typename T>
void foo(const T& t)
{
// 声明一个指向某个类型为T::bar的对象的指针
typename T::bar * p;
}
这样,编译器就确定了T::bar
是一个类型名,p也就自然地被解释为指向T::bar
类型的对象的指针了。
/** * 书本:【ThinkingInC++】 * 功能:关于模板的友元函数 * 时间:2014年10月16日16:30:49 * 作者:cutter_point */ #include <iostream> using namespace std; //前向声明 template<class T> class Friendly; template<class T> void f(const Friendly<T>&); template<class T> class Friendly { T t; public: Friendly(const T& theT) : t(theT) {} friend void f<> (const Friendly<T>&); //这里注意加一个<>是为了表示这是一个模板 void g() { f(*this); } }; void h() { f(Friendly<int>(1)); } template<class T> void f(const Friendly<T>& fo) { cout<<fo.t<<endl; } int main() { h(); Friendly<int>(2).g(); return 0; }
这里Friendly中的f的声明里的尖括号。这谁必须的,它告诉编译器f是一个模板。否则,编译器就会去寻找一个名为f的普通函数而不会找到他。
用模板定义操作符号
/** * 书本:【ThinkingInC++】 * 功能:定义模板的操作符 * 时间:2014年10月16日16:31:13 * 作者:cutter_point */ #include <iostream> using namespace std; //前向声明 template<class T> class Box; template<class T> Box<T> operator+(const Box<T>&, const Box<T>&); template<class T> ostream& operator<<(ostream&, const Box<T>&); //定义 template<class T> class Box { T t; public: Box(const T& theT) : t(theT) {} friend Box operator+<>(const Box<T>&, const Box<T>&); //表明这是一个模板 friend ostream& operator<< <>(ostream&, const Box<T>&); //同上 }; template<class T> Box<T> operator+(const Box<T>& b1, const Box<T>& b2) { return Box<T>(b1.t+b2.t); } template<class T> ostream& operator<<(ostream& os, const Box<T>& b) { return os<<'['<<b.t<<']'; } int main() { Box<int> b1(1), b2(2); cout<<b1+b2<<endl; return 0; }
这个程序有一个缺点,就是不能进行隐式转换,因为模板没有提供这些转换。
原文地址:http://blog.csdn.net/cutter_point/article/details/40150449