C++ Tutorial: Use std::tuple To Simulate Compact Heterogeneous Containers

Introduction

Standard C++ programming containers classes such as vector and list are homogeneous, meaning they can store only one type of objects at a time. However, in some cases it's more convenient to use a container of heterogeneous objects, which is where std::tuple comes in handy. std::tuple can store up to 10 objects of different types.

Suppose you need to design a function that retrieves three values from a database: an index number representing the month of the year, and two floating point numbers that represent the consumer's price index (CPI) of the relevant month, and the CPI of the previous month. Although you can split this function into two, it's more efficient and convenient to have one function that retrieves these values in one shot. Your first step consists of defining a tuple type i.e, a specialization of the class template std::tuple. Here's an example:

  #include <tuple>
  using namespace std;
  
  typedef tuple <int, double, double> CPIs;

Here's the function declaration:

  CPIs get_cpis(const Date& d);

In the absence of explicit initializers for the tuple's elements, the elements will be default-initialized:

  tuple <double, char> t2(3.55, 'a');// explicit 
  tuple <double, int, string> t3; // <0.0,0,string()>

Helper Functions

The Standard Library defines meta-functions and helper functions for handling tuples conveniently. Meta-functions use template meta-programming to compute their results at compile time. Helper functions are free-standing functions with short and intuitive names. Let's look at some of these.

To get the number of elements that a tuple type has, use the tuple_size() meta-function:

  #include <tuple>
  using namespace std;
  
  int elements=tuple_size<CPIs>::value;//3

To automate the creation of a tuple object, use the make_tuple() helper function. make_tuple() deduces the types of its arguments to create a tuple type. It returns a tuple object initialized with those arguments:

  CPIs mycpi=make_tuple(2, 0.1, 0.3);

To get the type of a tuple element, use the tuple_element() meta-function. This function is useful for traversing a tuple or when you want to create copies of a tuple's elements without knowing the elements' types in advance. tuple_element() takes an index and the tuple type (remember that tuples use zero-based indexing). In the following example, tuple_element() retrieves the type of the first tuple element. The result is used for declaring val, an object whose type is the same as that of the tuple's first element:

  tuple_element <0, tuple<int, int, char> >::type val;//int

What if you need to access the actual value of a tuple element rather than its type? Use the get<n> function template. Get takes an index and returns the corresponding element's value. The following listing uses tuple_element() to declare objects of the types of a tuple object's elements and then calls get<n> to copy their corresponding values:

  CPIs cpi=make_tuple(4, 0.1, -0.2);
  tuple_element <0,CPIs>::type val1;//int
  tuple_element <1,CPIs>::type val2;//double
  tuple_element <2,CPIs>::type val3;//double
  
  val1=get<0> (mycpi);//4
  val2=get<1> (mycpi);//0.1
  val3=get<2> (mycpi);//-0.2

Putting it all Together

Suppose you're designing a stock quote search engine that accepts a free text query. The engine retrieves the current stock price along with the stock's symbol. To represent the stock prices, you use a pair of integral values for the dollars and cents (a pair of integers rather than double guarantees accurate comparisons among other things), and a string for the stock symbol. You can represent the stock price like this:

  typedef tuple<int,int,string> StockPrice1;

This design is simple but not descriptive enough -- the reader has to guess that the first two integers are construed as a pair. An alternative design would use a layered structure:

  typedef tuple<int,int> Currency;
  typedef tuple<Currency, double, string > StockPrice2;

Regardless of your favorite representation, both designs exhibit the beauty of tuples. For example, to compare two StockPrice records you don't need to overload any operators. std::tuple already includes the relevant overloaded operators for you:

  StockPrice1 get_quote(const string& query);
  StockPrice1 a(620,24,"GOOG");
  StockPrice1 b=get_quote("Google Inc.");
  if (a!=b) //is it the same quote?
...

As an aside, you're probably wondering why I didn't use std::pair to represent Currency. The truth is that a pair is nothing but a tuple containing two members. Historically, std::pair inspired the authors of std::tuple to design a more generalized notion of a fixed-size heterogeneous container. Of course, it doesn't mean that you're advised to avoid std::pair;

Conclusion

Tuples were added to C++ programming as part of the Standard Library Technical Report One (TR1 for short) which is a fancy name for what would otherwise be dubbed a service pack for the C++98 Standard Library. Virtually, every standard-compliant C++ compiler supports std::tuple today. Additionally, tuples (as all other TR1 features) are highly portable, so you can use them without hesitation in cross-platform code.

The main advantage of std::tuple is automation. Instead of inventing a heterogeneous container on your own, std::tuple will be convenient so long as you don't need more than 10 elements and don't expect to insert or remove elements dynamically.

Related Articles



Comments

  • Oakley Sunglasses Stores

    Posted by gogogis on 05/14/2013 01:39pm

    I love your blog.. very nice colors & theme. Did you create this website yourself or did you hire someone to do it for you? Plz respond as I'm looking to design my own blog and would like to find out where u got this from. thanks a lot Abercrombie Fitch Garments Come In A Range Of Colors and Designs ray ban canada Oakley Sunglasses Famous For Its Quality and Innovation

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

Top White Papers and Webcasts

  • U.S. companies are desperately trying to recruit and hire skilled software engineers and developers, but there is simply not enough quality talent to go around. Tiempo Development is a nearshore software development company. Our headquarters are in AZ, but we are a pioneer and leader in outsourcing to Mexico, based on our three software development centers there. We have a proven process and we are experts at providing our customers with powerful solutions. We transform ideas into reality.

  • When individual departments procure cloud service for their own use, they usually don't consider the hazardous organization-wide implications. Read this paper to learn best practices for setting up an internal, IT-based cloud brokerage function that service the entire organization. Find out how this approach enables you to retain top-down visibility and control of network security and manage the impact of cloud traffic on your WAN.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date