导言
tuple库如何改进我们的程序?
- 从函数返回多个返回值
- 相关类型的组合
- 将数值组合起来
tuple比pair好在哪里?
标准库提供了一个 tuple 的特例,一个2-tuple, 名为 std::pair. 这个结构被用于标准库的容器,你可能在操作 std::map 的元素时已经留意到了。你也可以在容器类中存储 pair。当然,std::pair 不仅是为了给容器类使用的,它还有它自己的用途,它附带有一个方便的函数 std::make_pair, 可以自动地进行类型推断,还有一组操作符用于 pair 的比较。一个 tuple 的通常解决方案,而不仅仅是 2-tuples,会更加有用。Tuple 库所提供的还不是完全通用的,它最多可以允许10个元素的 tuple
(如果需要更多的,看起来不常见但也不是没有可能的,这个限制可以放松)。还有,这些 tuples 的效率与使用 struct 的手工解决方案同样高!
使用
以下是 Boost.Tuple 的部分接口,列出了最主要的一些函数。
namespace boost {
template <class T1, class T2, ..., class TM>
class tuple {
public:
tuple();
template <class P1, class P2..., class PM>
tuple(class P1, class P2, ..., PN);
template <class U1, class U2, ..., class UN>
tuple(const tuple<U1, U2, ..., UN>&);
tuple& operator=(const tuple&);
};
template<class T1, class T2, ..., class TN>
tuple<V1, V2, ..., VN>
make_tuple(const T1& t1, const T2& t2, ..., const TN& tn);
template<class T1, class T2, ..., class TN>
tuple<T1&, T2&, ..., TN>
tie(T1& t1, T2& t2, ..., TN& tn);
template <int I, class T1, class T2, ..., class TN>
RI get(tuple<T1, T2, ..., TN>& t);
template <int I, class T1, class T2, ..., class TN>
PI get(const tuple<T1, T2, ..., TN>& t);
template <class T1, class T2, ..., class TM, class U1, class U2, ..., class UM>
bool operator==(const tuple<T1, T2, ..., TM>& t, const tuple<U1, U2, ..., UM>& u);
template <class T1, class T2, ..., class TM, class U1, class U2, ..., class UM>
bool operator!=(const tuple<T1, T2, ..., TM>& t, const tuple<U1, U2, ..., UM>& u);
template <class T1, class T2, ..., class TN, class U1, class U2, ..., class UN>
bool operator<(const tuple<T1, T2, ..., TN>&, const tuple<U1, U2, ..., UN>&);
}
下面是使用用例:
#include <iostream>
#include <string>
#include "boost\tuple\tuple.hpp"
#include "boost\tuple\tuple_comparison.hpp"// for 比较tuples
#include "boost\tuple\tuple_io.hpp" // Tuples的流操作
using namespace std;
namespace bo = boost;
// 函数可以返回多个值
bo::tuples::tuple<int, double> get_values(int a, double b){
return bo::make_tuple(a, b);
// 缺省情况下,make_tuple 设置元素类型为非const, 非引用的
}
void main(){
// ------------- 构造tuples --------------------------------------
bo::tuple<int, double, string> triple(1, 3.14, "hello");
bo::tuple<short, int, long> another;// 它们都被初始化为0.
// make_tuple
int plain = 2;
int& ref = plain;
const int& cref = ref;
// 1. 带有一个 int 元素
bo::make_tuple(plain);
bo::make_tuple(ref);
bo::make_tuple(cref);
// 2. 带有一个 int& 元素,除了最后一个,它带的是一个 const int& 元素 (我们不能去掉 cref 的常量性):
bo::make_tuple(bo::ref(plain));
bo::make_tuple(bo::ref(ref));
bo::make_tuple(bo::ref(cref));
// 3. 带的是一个 const int& 元素
bo::make_tuple(bo::cref(plain));
bo::make_tuple(bo::cref(ref));
bo::make_tuple(bo::cref(cref));
// ----------- 访问tuple元素 ----------------------------------
bo::tuple<int, double, string> _triple(2, 3.14, "hello world");
int i = bo::tuples::get<0>(_triple); // 普通函数 get
double d = _triple.get<1>(); // 成员函数 get
string s = bo::get<2>(_triple);
cout << "_triple: " << i << ", " << d << ", " << s << endl;
auto _tuples = get_values(1, 2.9);// 调用返回多值的函数
cout << _tuples.get<0>() << ", " << _tuples.get<1>() << endl;
// ----------- 比较tuples -----------------------------
bo::tuple<int, string> tuple1(1, "hello");
bo::tuple<int, string> tuple2(2, "hello");
cout
<< std::boolalpha << '\n'
<< "tuple1 == tuple2: " << (tuple1 == tuple2) << '\n'
<< "tuple1 != tuple2: " << (tuple1 != tuple2) << '\n'
<< "tuple1 > tuple2: " << (tuple1 > tuple2) << '\n'
<< "tuple1 < tuple2: " << (tuple1 < tuple2) << '\n'
<< "tuple1 >= tuple2: " << (tuple1 >= tuple2) << '\n'
<< "tuple1 <= tuple2: " << (tuple1 <= tuple2) << '\n';
tuple2.get<0>() = tuple1.get<0>();
cout
<< std::boolalpha << '\n'
<< "tuple1 == tuple2: " << (tuple1 == tuple2) << '\n'
<< "tuple1 != tuple2: " << (tuple1 != tuple2) << '\n'
<< "tuple1 > tuple2: " << (tuple1 > tuple2) << '\n'
<< "tuple1 < tuple2: " << (tuple1 < tuple2) << '\n'
<< "tuple1 >= tuple2: " << (tuple1 >= tuple2) << '\n'
<< "tuple1 <= tuple2: " << (tuple1 <= tuple2) << '\n';
// -------------- 绑定 Tuple 元素到变量 ------------------
int _i; char _c; double _d;
bo::tuple<int, double> p(1, 2.0); //pair<int, double> p(1, 2.0); // OK! tie 也支持 std::pair.
bo::tie(_i, _d) = p;// bo::tie(_i, _d) = bo::tuple<int, double> (1, 2.0);
cout << "_i = "<< _i << endl;// _i = 1
bo::tie(_i, _c, _d) = bo::make_tuple(1, 'a', 5.5);
cout << _i << ", " << _c << ", " << _d << endl;
bo::tie(_i, _c) = make_pair(1, 'a');// pair只支持两个参数
cout << _i << ", " << _c << endl;
// -------------- tuples的流操作 ------------------
bo::tuple<float, int, string> _fis(1.0f, 2, "hello");
cout << _fis << endl;// (1 2 hello)
cout << bo::tuples::set_open('[') << bo::tuples::set_close(']') << bo::tuples::set_delimiter(',') << _fis;
cin.get();
}