A TR1 Tutorial: Class std::tr1::tuple

In a previous article, I gave a tutorial on the array class from the TR1 implementation released by Microsoft with the VC++ 2008 Feature Pack. In this article, I will talk about class tuple and the other classes and functions from the header with the same name, <tuple>.

Type tuple

A tuple is a sequence with a fixed number of elements of different types. The difference from an array is that a tuple is a heterogeneous sequence, whereas the array is a homogeneous sequence. Class tuple is a template class and is defined in the header <tuple> under the namespace std::tr1. Although theoretically a tuple can hold any number of elements (but finite), the implementation from VC++ 2008 Feature Pack only supports at most 15 elements.

Premises

In the examples from this tutorial, I will use a tuple with three elements, an int, a double, and a string. For the clarity of the samples, I will use this type definition:

typedef std::tr1::tuple<int, double, std::string> tuple_ids;

Also, I will use the following function for printing a tuple of the above type (I will provide details about accessing a tuple's elements in a following paragraph):

void print_tuple(const std::tr1::tuple<int, double,
                 std::string>& t)
{
   std::cout << std::tr1::get<0>(t) << " "
             << std::tr1::get<1>(t) << " "
             << std::tr1::get<2>(t) << std::endl;
}

Creating tuples

The simplest way to define a tuple is by using the default constructor:

tuple_ids t;
print_tuple(t);
0 0

Another option is using the constructor with parameters:

tuple_ids t(1, 2.5, "three");
print_tuple(t);

The output is:

1 2.5 three

A third option is creating a tuple using function make_tuple from the header <tuple>.

tuple_ids t = std::tr1::make_tuple(10, 20.5, "thirty");
print_tuple(t);
10 20.5 thirty

Tuple size

For the size of a tuple (number of elements), there is another template class called tuple_size, that has a member called value that represents the size of a tuple.

std::cout << "size: " << std::tr1::tuple_size<tuple_ids>::value
   << std::endl;
size: 3

Accessing tuple elements

To access elements from a tuple, you have to use function get:

  • Reading
  • tuple_ids t(1, 2.5, "three");
    std::cout << std::tr1::get<0>(t) << " "
              << std::tr1::get<1>(t) << " "
              << std::tr1::get<2>(t) << std::endl;
    

    the output is

    1 2.5 three
  • Writing
  • tuple_ids t;
    print_tuple(t);
    
    std::tr1::get<0>(t) = 10;
    std::tr1::get<1>(t) = 20.5;
    std::tr1::get<2>(t) = "thirty";
    print_tuple(t);
    

    the output is

    0 0
    10 20.5 thirty
    

A TR1 Tutorial: Class std::tr1::tuple

Types of elements

There is a class called tuple_element that wraps the type of a tuple element. This class has an internal typedef that is synonymous to the type of an element of a tuple (from the specified index).

tuple_ids t(100, 200.5, "three hundred");

std::tr1::tuple_element<0, tuple_ids>::type val1 =
   std::tr1::get<0>(t);
std::tr1::tuple_element<1, tuple_ids>::type val2 =
   std::tr1::get<1>(t);
std::tr1::tuple_element<2, tuple_ids>::type val3 =
   std::tr1::get<2>(t);

std::cout << "val1 = " << val1 << std::endl;
std::cout << "val2 = " << val2 << std::endl;
std::cout << "val3 = " << val3 << std::endl;
100 200.5 three hundred

Operators

The first provided operator is the assignment operator.

tuple_ids t1(1, 2.5, "three");
print_tuple(t1);

tuple_ids t2;
t2 = t1;
print_tuple(t2);

tuple_ids t3(100, 200.5, "three hundred");
t1 = t3;
print_tuple(t1);
1 2.5 three
1 2.5 three
100 200.5 three hundred

Then, there are the == and != operators. The first operator (==) returns true if the size is 0 or each element from the first tuple is equal to the corresponding element from the second tuple. The second operator (!=) returns false if the size is 0 or at least one element from the first tuple is not equal to the corresponding element from the second tuple. Comparison can only be performed for tuples of the same type.

tuple_ids t1(1, 2.0, "one");
tuple_ids t2(2, 2.0, "one");

std::cout << "t1 == t1: " << std::boolalpha << (t1 == t1)
   << std::endl;
std::cout << "t1 == t2: " << std::boolalpha << (t1 == t2)
   << std::endl;
t1 == t1: true
t1 == t2: false

Other implemented operators are >, >=, < si <=. They are all defined in terms of operator <.

This operator returns true when the size of the tuple is greater than 0 and the first element (no matter the index) from the first tuple is smaller than the corresponding element from the second tuple.

tuple_ids t1(1, 2.0, "one");
tuple_ids t2(2, 2.0, "one");
tuple_ids t3(1, 3.0, "one");
tuple_ids t4(1, 2.0, "four");

std::cout << "t1 < t2: " << std::boolalpha << (t1 < t2)
   << std::endl;
std::cout << "t1 < t3: " << std::boolalpha << (t1 < t3)
   << std::endl;
std::cout << "t1 < t4: " << std::boolalpha << (t1 < t4)
   << std::endl;
t1 < t2: true
t1 < t3: true
t1 < t4: false

Tying variables in a tuple

You can create a tuple from references to objects by using function tie.

tuple_ids t(1, 2.5, "three")

int v1 = 10;
double v2 = 20.5;
std::string v3 = "thirty";
std::cout << "before tying..." << std::endl;
std::cout << v1 << " " 
          << v2 << " "
          << v3 << std::endl;

std::tr1::tie(v1, v2, v3) = t;
std::cout << "after tying..." << std::endl;
std::cout << v1 << " " 
          << v2 << " "
          << v3 << std::endl;
before tying...
10 20.5 thirty
after tying...
1 2.5 three

A TR1 Tutorial: Class std::tr1::tuple

Swapping

You can swap the content of two tuples either by using the method swap from class tuple, or the function with the same name from header <tuple>.

tuple_ids a(1, 2, "three");
tuple_ids b(4, 5, "six");

std::cout << "before swapping" << std::endl;
print_tuple(a);
print_tuple(b);

std::cout << "after first swapping" << std::endl;
a.swap(b);
print_tuple(a);
print_tuple(b);

std::cout << "after second swapping" << std::endl;
std::tr1::swap(a, b);
print_tuple(a);
print_tuple(b);
before swapping
1 2 three
4 5 six
after first swapping
4 5 six
1 2 three
after second swapping
1 2 three
4 5 six

Debugger Support

As in the case of array and the other STL containers, the debugger shows the content of a tuple in a friendly manner, as shown in the following image.

[tupledebugger.png]

Conclusions

Although class array is useful for homogenous sequences with a given length, class tuple is useful for heterogenous sequences with a given length. It allows you to define fixed sequences with elements of different types.



About the Author

Marius Bancila

Marius Bancila is a Microsoft MVP for VC++. He works as a software developer for a Norwegian-based company. He is mainly focused on building desktop applications with MFC and VC#. He keeps a blog at www.mariusbancila.ro/blog, focused on Windows programming. He is the co-founder of codexpert.ro, a community for Romanian C++/VC++ programmers.

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • This paper introduces IBM Java on the IBM PowerLinux 7R2 server and describes IBM's implementation of the Java platform, which includes IBM's Java Virtual Machine and development toolkit.

  • Not all enterprise applications are created equal. Sophisticated applications need developer support but other more basic apps do not. With the right tools, everyone is a potential app developer with ideas and a perspective to share. Trends such as low-code development and model driven development are fundamentally changing how and who creates applications. Is your organization ready? Read this report and learn: The seven personas of enterprise app delivery How application ownership is spreading to the …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds