boost::tuple<unsigned int,std::string,base*> tup5; tup5=tup4; tup5.get<2>()->test(); boost::tuple<int,std::string,derived&> tup6(12,"Example",d); boost::tuple<unsigned int,std::string,base&> tup7(tup6); tup7.get<2>()->test(); In both cases, derived::test is called, which is exactly what we want. tup6 and tup7 are not assignable because you can't assign to a reference, which is why tup7 is copy constructed from tup6 and tup6 is initialized with d. Because tup4 and tup5 use pointers for their third element, they do support assignment. Note that typically smart pointers are best in tuples (as opposed to raw pointers), because they alleviate the need to manage the lifetime of the resources to which the pointers refer. However, as tup4 and tup5 show, pointers don't always refer to something requiring memory management in the tuples. (Refer to "Library 1: Smart_ptr 1" for the details on the powerful smart pointers in Boost.) Comparing Tuples To compare tuples, you must include "boost/tuple/tuple_comparison.hpp". The relational tuple operators are ==,!=,<,>,<= and >=, and they invoke the same operator for each element pair, in order, in the tuples being compared. These pair-wise comparisons short circuit, meaning that they only compare as many pairs as needed to arrive at the correct result. Only tuples with the same number of elements can be compared and, as should be obvious, the corresponding element types in the two tuples must be comparable. The test for equality returns TRue if all of the element pairs of the two tuples are also equal. If any one equality comparison between element pairs returns false, so does operator==. The inequality test is analogous, but returns the inverse result. The rest of the relational operators perform lexicographical comparisons. Here's a sample program showing the comparison operators in action. #include <iostream> #include <string> #include "boost/tuple/tuple.hpp" #include "boost/tuple/tuple_comparison.hpp" int main() { boost::tuple<int,std::string> tup1(11,"Match?"); boost::tuple<short,std::string> tup2(12,"Match?"); std::cout << std::boolalpha; std::cout << "Comparison: tup1 is less than tup2\n"; std::cout << "tup1==tup2: " << (tup1==tup2) << '\n'; std::cout << "tup1!=tup2: " << (tup1!=tup2) << '\n'; std::cout << "tup1<tup2: " << (tup1<tup2) << '\n'; std::cout << "tup1>tup2: " << (tup1>tup2) << '\n'; std::cout << "tup1<=tup2: " << (tup1<=tup2) << '\n'; std::cout << "tup1>=tup2: " << (tup1>=tup2) << '\n'; tup2.get<0>()=boost::get<0>(tup1); //tup2=tup1 also works std::cout << "\nComparison: tup1 equals tup2\n"; std::cout << "tup1==tup2: " << (tup1==tup2) << '\n'; std::cout << "tup1!=tup2: " << (tup1!=tup2) << '\n'; std::cout << "tup1<tup2: " << (tup1<tup2) << '\n'; std::cout << "tup1>tup2: " << (tup1>tup2) << '\n'; std::cout << "tup1<=tup2: " << (tup1<=tup2) << '\n'; std::cout << "tup1>=tup2: " << (tup1>=tup2) << '\n'; } As you can see, the two tuples, tup1 and tup2, don't have exactly the same type, but the types are still comparable. For the first set of comparisons, the tuples have different values for the first element, but for the second set, the tuples are equal. This is the output from running the program. Comparison: tup1 is less than tup2 tup1==tup2: false tup1!=tup2: true tup1<tup2: true tup1>tup2: false tup1<=tup2: true tup1>=tup2: false Comparison: tup1 equals tup2 tup1==tup2: true tup1!=tup2: false tup1<tup2: false tup1>tup2: false tup1<=tup2: true tup1>=tup2: true One important aspect of the support for comparisons is that tuples can be sorted, which means they can be stored in associative containers. It is sometimes desirable to sort based on one of the elements of a tuple (creating a strict weak ordering), which we can accomplish with a simple, generic solution. template <int Index> class element_less { public: template <typename Tuple> bool operator()(const Tuple& lhs,const Tuple& rhs) const { return boost::get<Index>(lhs)<boost::get<Index>(rhs); } }; This shows one of the advantages of accessing elements by index rather than by name; it is very easy to create generic constructs that perform powerful operations. The sorting performed by our element_less can be used like this: #include <iostream> #include <vector> #include "boost/tuple/tuple.hpp" #include "boost/tuple/tuple_comparison.hpp" template <int Index> class element_less { public: template <typename Tuple> bool operator()(const Tuple& lhs,const Tuple& rhs) const { return boost::get<Index>(lhs)<boost::get<Index>(rhs); } }; int main() { typedef boost::tuple<short,int,long,float,double,long double> num_tuple; std::vector<num_tuple> vec; vec.push_back(num_tuple(6,2)); vec.push_back(num_tuple(7,1)); vec.push_back(num_tuple(5)); std::sort(vec.begin(),vec.end(),element_less<1>()); std::cout << "After sorting: " << vec[0].get<0>() << '\n' << vec[1].get<0>() << '\n' << vec[2].get<0>() << '\n'; } vec is populated with three elements. The sorting is performed on the second element of the tuples using the element_less<1> function object from the template that we created earlier. There are more applications for this kind of function object, such as when searching for certain tuple elements. Tying Tuple Elements to Variables A handy feature of the Boost.Tuple library is "tying" tuples to variables. Tiers are tuples created by the overloaded function template boost::tie, such that all of the elements are non-const reference types. As a result, ties must be initialized with lvalues, and thus tie's arguments are non-const reference types, too. Because the resulting tuples have non-const reference elements, any assignment to the elements of such a tuple are assignments through non-const references to the lvalues with which tie was called. This ties existing variables to a tuple, hence the name! The following example first shows the obvious way of getting values out of a returned tuple. Then, it shows the same operation using a tied tuple to assign values directly to variables. To make the example more interesting, we'll begin by defining a function that returns the greatest common divisor and the least common multiple of two values. The values are, of course, grouped together as a tuple return type. You'll notice that the functions for calculating the greatest common divisor and least common multiple come from another Boost libraryBoost.Math. #include <iostream> #include "boost/tuple/tuple.hpp" #include "boost/math/common_factor.hpp" boost::tuple<int,int> gcd_lcm(int val1,int val2) { return boost::make_tuple( boost::math::gcd(val1,val2), boost::math::lcm(val1,val2)); } int main() { //The "old" way boost::tuple<int,int> tup; tup=gcd_lcm(12,18); int gcd=tup.get<0>()); int lcm=tup.get<1>()); std::cout << "Greatest common divisor: " << gcd << '\n'; std::cout << "Least common multiple: " << lcm << '\n'; //The "new" way boost::tie(gcd,lcm)=gcd_lcm(15,20); std::cout << "Greatest common divisor: " << gcd << '\n'; std::cout << "Least common multiple: " << lcm << '\n'; } In some cases, we may not be interested in all of the elements of the returned tuple, and this too is supported by tie. There is a special objectboost:: tuples::ignorethat discards a tuple element's value. If in the preceding example we were only interested in the greatest common divisor, we could have expressed it as follows: boost::tie(gcd,boost::tuples::ignore)=gcd_lcm(15,20); The alternative is to create a variable, pass it to tie, and then ignore it in the rest of the current scope. That leaves maintainers to question the variable's existence. Using ignore clearly proclaims that the code doesn't use that value from the tuple. Note that tie also supports std::pair. The usage is just like tying values from boost::tuples. std::pair<short,double> p(3,0.141592); short s; double d; boost::tie(s,d)=p; Tying tuples is more than a mere convenience; it helps make the code clearer. Streaming Tuples Each of the examples in this chapter extracted the elements of tuples just to be able to stream them to std::cout. This works, but there's actually an easier way. The tuple library supports both input and output streaming; operator>> and operator<< are overloaded for tuples. There are also manipulators to change the default delimiters used for input and output streaming. Changing the delimiters for input changes what operator>> looks for to recognize element values. Let's examine these things in a simple program that reads and writes tuples. Note that to use tuple streaming, you need to include the header "boost/tuple/tuple_io.hpp". #include <iostream> #include "boost/tuple/tuple.hpp" #include "boost/tuple/tuple_io.hpp" . overloaded for tuples. There are also manipulators to change the default delimiters used for input and output streaming. Changing the delimiters for input changes what operator>> looks for to. same type, but the types are still comparable. For the first set of comparisons, the tuples have different values for the first element, but for the second set, the tuples are equal. This. sorting is performed on the second element of the tuples using the element_less<1> function object from the template that we created earlier. There are more applications for this kind