Most efficient way to process all items in an unknown container? - c++

I'm doing a computation in C++ and it has to be as fast as possible (it is executed 60 times per second with possibly large data). During the computation, a certain set of items have to be processed. However, in different cases, different implementations of the item storage are optimal, so i need to use an abstract class for that.
My question is, what is the most common and most efficient way to do an action with each of the items in C++? (I don't need to change the structure of the container during that.) I have thought of two possible solutions:
Make iterators for the storage classes. (They're also mine, so i can add it.) This is common in Java, but doesn't seem very 'C' to me:
class Iterator {
public:
bool more() const;
Item * next();
}
Add sort of an abstract handler, which would be overriden in the computation part and would include the code to be called on each item:
class Handler {
public:
virtual void process(Item &item) = 0;
}
(Only a function pointer wouldn't be enough because it has to also bring some other data.)
Something completely different?
The second option seems a bit better to me since the items could in fact be processed in a single loop without interruption, but it makes the code quite messy as i would have to make quite a lot of derived classes. What would you suggest?
Thanks.
Edit: To be more exact, the storage data type isn't exactly just an ADT, it has means of only finding only a specific subset of the elements in it based on some parameters, which i need to then process, so i can't prepare all of them in an array or something.

#include <algorithm>
Have a look at the existing containers provided by the C++ standard, and functions such as for_each.
For a comparison of C++ container iteration to interfaces in "modern" languages, see this answer of mine. The other answers have good examples of what the idiomatic C++ way looks like in practice.
Using templated functors, as the standard containers and algorithms do, will definitely give you a speed advantage over virtual dispatch (although sometimes the compiler can devirtualize calls, don't count on it).

C++ has iterators already. It's not a particularly "Java" thing. (Note that their interface is different, though, and they're much more efficient than their Java equivalents)
As for the second approach, calling a virtual function for every element is going to hurt performance if you're worried about throughput.
If you can (pre-)sort your data so that all objects of the same type are stored consecutively, then you can select the function to call once, and then apply it to all elements of that type. Otherwise, you'll have to go through the indirection/type check of a virtual function or another mechanism to perform the appropriate action for every individual element.

What gave you the impression that iterators are not very C++-like? The standard library is full of them (see this), and includes a wide range of algorithms that can be used to effectively perform tasks on a wide range of standard container types.
If you use the STL containers you can save re-inventing the wheel and get easy access to a wide variety of pre-defined algorithms. This is almost always better than writing your own equivalent container with an ad-hoc iteration solution.

A function template perhaps:
template <typename C>
void process(C & c)
{
typedef typename C::value_type type;
for (type & x : c) { do_something_with(x); }
}
The iteration will use the containers iterators, which is generally as efficient as you can get.
You can specialize the template for specific containers.

Related

Why not implement contains function in c++ Containers?

My initial question was: why does in C++ the contains() function miss in Containers?
So I looked for an explanation and I found something interesting about why some other function are not implemented in all the Containers (essentially because of performance issues and convenience).
I know that you can use the find function from algorithm library or you can just write your own function with Iterator, but what I can't understand is why in set, for example, the contains function(where it's called find) is implemented, whereas in vector or queue it is not.
It's pretty clear to me too why Container classes does not share a common interface like Collections do in Java (thanks to this answer) but in this case I can't find the reason why not implement the contains() function in all the Containers classes (or at least in some like vector).
Thank you
The reason why std::set implements its own find is that the "generic" std::find does a linear search, while std::set can do a lot better than that by searching its tree representation in O(log2 n ).
std::vector and std::list, on the other hand, cannot be searched faster than in linear time, so they rely on std::find implementation.
Note that you are still allowed to apply std::find to std::set to search it linearly; it just wouldn't be as efficient as using set's own find member function.
std::set<int> s {1, 2, 3, 4, 5, 6};
auto res = std::find(s.begin(), s.end(), 3);
std::cout << *res << std::endl; // prints 3
Because it's a bad design pattern. If you're using "find" on a linear container repeatedly, there's a problem with your code. The average and worst case time complexity is still O(n), which means you've made a bad choice.
For example, std::map and std::unordered_map have find member functions which allows O(logn) and O(1) lookups. This is because the container employs efficient item lookup via these methods: that is how the container should be used.
If you've weighed all the options, and decided a linear container is the best model for your data, but do need to find an element in rare occasions, std::find() allows you to do just that. You shouldn't rely on it. I view this as an antipattern in Python and Java, and a benefit in C++.
Just as a personal note, 3 years ago, when I was a beginner coder, I wrote if mydict in list: do_something() a lot. I thought this was a good idea, because Python makes list item membership idiomatic. I didn't know better. This led me to produce awful code, until I learned why linear searches are so inefficient compared to binary searches and hashmap lookups. A programming language or framework should enable good design patterns, and discourage bad ones. Enabling linear searches is a bad design pattern.
Other answers for some reason focus on complexity of generalized and per-container find methods. However they fail to explain the OP's question. The actual reason for a lack of helpful utility methods originates from the way the classes from different files are used in C++. If every container that does not hold any special properties would have contains method executing generic search with linear complexity we would stuck either with situation when each container header also includes <algorithm> or when each container header reimplements it's own find algorithm (which is even worse). And the pretty large document build during compilation of each translation unit after preprocessor includes (that is copy-pastes) every included header would grow even bigger. Compilation would take even more time. And the rather cryptic compilation error messaged may get even longer. That old principle of not making member function when a non-member function can do the job (and to include only stuff you are going to use) exists for a reason.
Note that there was a proposal recently for uniform call syntax that may allow to kinda mix-in utility methods into classes. If it goes live it probably will be possible to write extension functions like this:
template< typename TContainer, typename TItem > bool
contains(TContainer const & container, TItem const & item)
{
// Some implementation possibly calling container member find
// or ::std::find if container has none...
}
::std::vector< int > registry;
registry.contains(3); // false
There is a good reason that containers do not share a "common (inherited) interface" (like in Java) and it is what makes the C++ generics so powerful. Why write code for every container when you can write it only once for all containers? This is one of the main principles the STL was built on.
If using containers relied on member functions from a common inherited interface you would have to write a find function for every container. That is wasteful and poor engineering. Good design says if you can write code in only one place you should because you only have to remove the bugs from that one place, and fixing a bug in one place fixes the bug everywhere.
So the philosophy behind the STL is to separate the algorithms from the containers so that you only have to write the algorithm once and it works for all containers. Once the algorithm is debugged, it is debugged for all containers.
A fly in that ointment is that some containers can make more efficient decisions due to their internal structure. For those containers a type specific function has been added which will take advantage of that efficiency.
But most functions should be separate from the containers. It is called decoupling and it reduces bugs while promoting code reuse, often much more so than polymorphism which is what libraries like Java containers use (a common inherited interface).

Method operating on container: hardcode the container type, or use generic template iterators?

I have code where, conceptually, my input is some container of Foo objects. The code "processes" these objects one by one, and the desired result is to fill up a container of FooProduct result objects.
I only need a single pass through the input container. The "processing" is stateful (this isn't an std::transform()) and the number of result objects is independent of the number of input objects.
Offhand, I could see two obvious ways to define the API here.
The easiest way to do this is to hardcode a specific type of container. For example, I could decide I'm expecting vector parameters, e.g.:
void ProcessContainerOfFoos(const std::vector<Foo>& in, std::vector<FooProduct>&out);
But, I don't really have any reason to limit client code to a particular type of container. Instead of constraining the parameter types specifically to vector, I could make the method generic and use iterators as template parameters:
/**
* #tparam Foo_InputIterator_T An input iterator giving objects of type Foo.
* #tparam FooProduct_OutputIterator_T An output iterator writing objects
* of type FooProduct.
*/
template<typename Foo_InputIterator_T, typename FooProduct_OutputIterator_T >
void ProcessContainerOfFoos(Foo_InputIterator_T first, Foo_InputIterator_T last,
FooProduct_OutputIterator_T out);
I'm debating between these two formulations.
Considerations
To me, the first code seems to me to be "easier" and the second seems "more correct":
Non-template types make the signature clearer; I don't need to explain in the documentation what types to use and what the constraints on the template parameter are.
Without templates I can hide the implementation in the .cpp file; with templates I'll need to expose the implementation in a header file, forcing client code to include anything I need for the actual processing logic.
The templated version feels like it expresses my intention more clearly, because I'd rather be indifferent to what container type is used.
The templated version is more flexible and testable - for example, in my code I might be using some custom data structure MySuperEfficientVector , but I'd still be able to test MyFooProcessor without any dependency on the custom class.
Beyond subjective choice given these considerations, is there a major reason to choose one of these over the other? Likewise, is there a better way to construct this API which I'm missing?
Besides the considerations that you've already listed:
The template version allows the client code to pass any iterator
range, for example a sub-range or reverse iterators, not just an entire container from begin to end.
The template version allows passing value types other than Foo. For this to be useful, the processing must be generic of course.
If the template works with only specific value type and the user tries to use iterators to wrong type, the error message might not be very descriptive of their mistake. If this is a concern, you can give the user a better error using type traits: static_assert(std::is_same<Iter::value_type, Foo>::value, "I want my Foo"); Until concepts proposal is added to the standard, there is no good way to communicate the requirements of a template type in the signature to the user.
There is also the option to provide both functions. The hard coded one can delegate to the templated version. This gives you the advantages of both versions at the expense of bloating your api.
It depends. If this function is going to be used with vectors for the time beeing why bother?
I suggest doing templated version only when it becomes necessary. Predicting such things in advance is hard.

Are there any C++ language obstacles that prevent adopting D ranges?

This is a C++ / D cross-over question. The D programming language has ranges that -in contrast to C++ libraries such as Boost.Range- are not based on iterator pairs. The official C++ Ranges Study Group seems to have been bogged down in nailing a technical specification.
Question: does the current C++11 or the upcoming C++14 Standard have any obstacles that prevent adopting D ranges -as well as a suitably rangefied version of <algorithm>- wholesale?
I don't know D or its ranges well enough, but they seem lazy and composable as well as capable of providing a superset of the STL's algorithms. Given their claim to success for D, it would seem very nice to have as a library for C++. I wonder how essential D's unique features (e.g. string mixins, uniform function call syntax) were for implementing its ranges, and whether C++ could mimic that without too much effort (e.g. C++14 constexpr seems quite similar to D compile-time function evaluation)
Note: I am seeking technical answers, not opinions whether D ranges are the right design to have as a C++ library.
I don't think there is any inherent technical limitation in C++ which would make it impossible to define a system of D-style ranges and corresponding algorithms in C++. The biggest language level problem would be that C++ range-based for-loops require that begin() and end() can be used on the ranges but assuming we would go to the length of defining a library using D-style ranges, extending range-based for-loops to deal with them seems a marginal change.
The main technical problem I have encountered when experimenting with algorithms on D-style ranges in C++ was that I couldn't make the algorithms as fast as my iterator (actually, cursor) based implementations. Of course, this could just be my algorithm implementations but I haven't seen anybody providing a reasonable set of D-style range based algorithms in C++ which I could profile against. Performance is important and the C++ standard library shall provide, at least, weakly efficient implementations of algorithms (a generic implementation of an algorithm is called weakly efficient if it is at least as fast when applied to a data structure as a custom implementation of the same algorithm using the same data structure using the same programming language). I wasn't able to create weakly efficient algorithms based on D-style ranges and my objective are actually strongly efficient algorithms (similar to weakly efficient but allowing any programming language and only assuming the same underlying hardware).
When experimenting with D-style range based algorithms I found the algorithms a lot harder to implement than iterator-based algorithms and found it necessary to deal with kludges to work around some of their limitations. Of course, not everything in the current way algorithms are specified in C++ is perfect either. A rough outline of how I want to change the algorithms and the abstractions they work with is on may STL 2.0 page. This page doesn't really deal much with ranges, however, as this is a related but somewhat different topic. I would rather envision iterator (well, really cursor) based ranges than D-style ranges but the question wasn't about that.
One technical problem all range abstractions in C++ do face is having to deal with temporary objects in a reasonable way. For example, consider this expression:
auto result = ranges::unique(ranges::sort(std::vector<int>{ read_integers() }));
In dependent of whether ranges::sort() or ranges::unique() are lazy or not, the representation of the temporary range needs to be dealt with. Merely providing a view of the source range isn't an option for either of these algorithms because the temporary object will go away at the end of the expression. One possibility could be to move the range if it comes in as r-value, requiring different result for both ranges::sort() and ranges::unique() to distinguish the cases of the actual argument being either a temporary object or an object kept alive independently. D doesn't have this particular problem because it is garbage collected and the source range would, thus, be kept alive in either case.
The above example also shows one of the problems with possibly lazy evaluated algorithm: since any type, including types which can't be spelled out otherwise, can be deduced by auto variables or templated functions, there is nothing forcing the lazy evaluation at the end of an expression. Thus, the results from the expression templates can be obtained and the algorithm isn't really executed. That is, if an l-value is passed to an algorithm, it needs to be made sure that the expression is actually evaluated to obtain the actual effect. For example, any sort() algorithm mutating the entire sequence clearly does the mutation in-place (if you want a version doesn't do it in-place just copy the container and apply the in-place version; if you only have a non-in-place version you can't avoid the extra sequence which may be an immediate problem, e.g., for gigantic sequences). Assuming it is lazy in some way the l-value access to the original sequence provides a peak into the current status which is almost certainly a bad thing. This may imply that lazy evaluation of mutating algorithms isn't such a great idea anyway.
In any case, there are some aspects of C++ which make it impossible to immediately adopt the D-sytle ranges although the same considerations also apply to other range abstractions. I'd think these considerations are, thus, somewhat out of scope for the question, too. Also, the obvious "solution" to the first of the problems (add garbage collection) is unlikely to happen. I don't know if there is a solution to the second problem in D. There may emerge a solution to the second problem (tentatively dubbed operator auto) but I'm not aware of a concrete proposal or how such a feature would actually look like.
BTW, the Ranges Study Group isn't really bogged down by any technical details. So far, we merely tried to find out what problems we are actually trying to solve and to scope out, to some extend, the solution space. Also, groups generally don't get any work done, at all! The actual work is always done by individuals, often by very few individuals. Since a major part of the work is actually designing a set of abstractions I would expect that the foundations of any results of the Ranges Study Group is done by 1 to 3 individuals who have some vision of what is needed and how it should look like.
My C++11 knowledge is much more limited than I'd like it to be, so there may be newer features which improve things that I'm not aware of yet, but there are three areas that I can think of at the moment which are at least problematic: template constraints, static if, and type introspection.
In D, a range-based function will usually have a template constraint on it indicating which type of ranges it accepts (e.g. forward range vs random-access range). For instance, here's a simplified signature for std.algorithm.sort:
auto sort(alias less = "a < b", Range)(Range r)
if(isRandomAccessRange!Range &&
hasSlicing!Range &&
hasLength!Range)
{...}
It checks that the type being passed in is a random-access range, that it can be sliced, and that it has a length property. Any type which does not satisfy those requirements will not compile with sort, and when the template constraint fails, it makes it clear to the programmer why their type won't work with sort (rather than just giving a nasty compiler error from in the middle of the templated function when it fails to compile with the given type).
Now, while that may just seem like a usability improvement over just giving a compilation error when sort fails to compile because the type doesn't have the right operations, it actually has a large impact on function overloading as well as type introspection. For instance, here are two of std.algorithm.find's overloads:
R find(alias pred = "a == b", R, E)(R haystack, E needle)
if(isInputRange!R &&
is(typeof(binaryFun!pred(haystack.front, needle)) : bool))
{...}
R1 find(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
if(isForwardRange!R1 && isForwardRange!R2 &&
is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool) &&
!isRandomAccessRange!R1)
{...}
The first one accepts a needle which is only a single element, whereas the second accepts a needle which is a forward range. The two are able to have different parameter types based purely on the template constraints and can have drastically different code internally. Without something like template constraints, you can't have templated functions which are overloaded on attributes of their arguments (as opposed to being overloaded on the specific types themselves), which makes it much harder (if not impossible) to have different implementations based on the genre of range being used (e.g. input range vs forward range) or other attributes of the types being used. Some work has been being done in this area in C++ with concepts and similar ideas, but AFAIK, C++ is still seriously lacking in the features necessary to overload templates (be they templated functions or templated types) based on the attributes of their argument types rather than specializing on specific argument types (as occurs with template specialization).
A related feature would be static if. It's the same as if, except that its condition is evaluated at compile time, and whether it's true or false will actually determine which branch is compiled in as opposed to which branch is run. It allows you to branch code based on conditions known at compile time. e.g.
static if(isDynamicArray!T)
{}
else
{}
or
static if(isRandomAccessRange!Range)
{}
else static if(isBidirectionalRange!Range)
{}
else static if(isForwardRange!Range)
{}
else static if(isInputRange!Range)
{}
else
static assert(0, Range.stringof ~ " is not a valid range!");
static if can to some extent obviate the need for template constraints, as you can essentially put the overloads for a templated function within a single function. e.g.
R find(alias pred = "a == b", R, E)(R haystack, E needle)
{
static if(isInputRange!R &&
is(typeof(binaryFun!pred(haystack.front, needle)) : bool))
{...}
else static if(isForwardRange!R1 && isForwardRange!R2 &&
is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool) &&
!isRandomAccessRange!R1)
{...}
}
but that still results in nastier errors when compilation fails and actually makes it so that you can't overload the template (at least with D's implementation), because overloading is determined before the template is instantiated. So, you can use static if to specialize pieces of a template implementation, but it doesn't quite get you enough of what template constraints get you to not need template constraints (or something similar).
Rather, static if is excellent for doing stuff like specializing only a piece of your function's implementation or for making it so that a range type can properly inherit the attributes of the range type that it's wrapping. For instance, if you call std.algorithm.map on an array of integers, the resultant range can have slicing (because the source range does), whereas if you called map on a range which didn't have slicing (e.g. the ranges returned by std.algorithm.filter can't have slicing), then the resultant ranges won't have slicing. In order to do that, map uses static if to compile in opSlice only when the source range supports it. Currently, map 's code that does this looks like
static if (hasSlicing!R)
{
static if (is(typeof(_input[ulong.max .. ulong.max])))
private alias opSlice_t = ulong;
else
private alias opSlice_t = uint;
static if (hasLength!R)
{
auto opSlice(opSlice_t low, opSlice_t high)
{
return typeof(this)(_input[low .. high]);
}
}
else static if (is(typeof(_input[opSlice_t.max .. $])))
{
struct DollarToken{}
enum opDollar = DollarToken.init;
auto opSlice(opSlice_t low, DollarToken)
{
return typeof(this)(_input[low .. $]);
}
auto opSlice(opSlice_t low, opSlice_t high)
{
return this[low .. $].take(high - low);
}
}
}
This is code in the type definition of map's return type, and whether that code is compiled in or not depends entirely on the results of the static ifs, none of which could be replaced with template specializations based on specific types without having to write a new specialized template for map for every new type that you use with it (which obviously isn't tenable). In order to compile in code based on attributes of types rather than with specific types, you really need something like static if (which C++ does not currently have).
The third major item which C++ is lacking (and which I've more or less touched on throughout) is type introspection. The fact that you can do something like is(typeof(binaryFun!pred(haystack.front, needle)) : bool) or isForwardRange!Range is crucial. Without the ability to check whether a particular type has a particular set of attributes or that a particular piece of code compiles, you can't even write the conditions which template constraints and static if use. For instance, std.range.isInputRange looks something like this
template isInputRange(R)
{
enum bool isInputRange = is(typeof(
{
R r = void; // can define a range object
if (r.empty) {} // can test for empty
r.popFront(); // can invoke popFront()
auto h = r.front; // can get the front of the range
}));
}
It checks that a particular piece of code compiles for the given type. If it does, then that type can be used as an input range. If it doesn't, then it can't. AFAIK, it's impossible to do anything even vaguely like this in C++. But to sanely implement ranges, you really need to be able to do stuff like have isInputRange or test whether a particular type compiles with sort - is(typeof(sort(myRange))). Without that, you can't specialize implementations based on what types of operations a particular range supports, you can't properly forward the attributes of a range when wrapping it (and range functions wrap their arguments in new ranges all the time), and you can't even properly protect your function against being compiled with types which won't work with it. And, of course, the results of static if and template constraints also affect the type introspection (as they affect what will and won't compile), so the three features are very much interconnected.
Really, the main reasons that ranges don't work very well in C++ are the some reasons that metaprogramming in C++ is primitive in comparison to metaprogramming in D. AFAIK, there's no reason that these features (or similar ones) couldn't be added to C++ and fix the problem, but until C++ has metaprogramming capabilities similar to those of D, ranges in C++ are going to be seriously impaired.
Other features such as mixins and Uniform Function Call Syntax would also help, but they're nowhere near as fundamental. Mixins would help primarily with reducing code duplication, and UFCS helps primarily with making it so that generic code can just call all functions as if they were member functions so that if a type happens to define a particular function (e.g. find) then that would be used instead of the more general, free function version (and the code still works if no such member function is declared, because then the free function is used). UFCS is not fundamentally required, and you could even go the opposite direction and favor free functions for everything (like C++11 did with begin and end), though to do that well, it essentially requires that the free functions be able to test for the existence of the member function and then call the member function internally rather than using their own implementations. So, again you need type introspection along with static if and/or template constraints.
As much as I love ranges, at this point, I've pretty much given up on attempting to do anything with them in C++, because the features to make them sane just aren't there. But if other folks can figure out how to do it, all the more power to them. Regardless of ranges though, I'd love to see C++ gain features such as template constraints, static if, and type introspection, because without them, metaprogramming is way less pleasant, to the point that while I do it all the time in D, I almost never do it in C++.

What are good use-cases for tuples in C++11?

What are good use-cases for using tuples in C++11? For example, I have a function that defines a local struct as follows:
template<typename T, typename CmpF, typename LessF>
void mwquicksort(T *pT, int nitem, const int M, CmpF cmp, LessF less)
{
struct SI
{
int l, r, w;
SI() {}
SI(int _l, int _r, int _w) : l(_l), r(_r), w(_w) {}
} stack[40];
// etc
I was considering to replace the SI struct with an std::tuple<int,int,int>, which is a far shorter declaration with convenient constructors and operators already predefined, but with the following disadvantages:
Tuple elements are hidden in obscure, implementation-defined structs. Even though Visual studio interprets and shows their contents nicely, I still can't put conditional breakpoints that depend on value of tuple elements.
Accessing individual tuple fields (get<0>(some_tuple)) is far more verbose than accessing struct elements (s.l).
Accessing fields by name is far more informative (and shorter!) than by numeric index.
The last two points are somewhat addressed by the tie function. Given these disadvantages, what would be a good use-case for tuples?
UPDATE Turns out that VS2010 SP1 debugger cannot show the contents of the following array std::tuple<int, int, int> stack[40], but it works fine when it's coded with a struct. So the decision is basically a no-brainer: if you'll ever have to inspect its values, use a struct [esp. important with debuggers like GDB].
It is an easy way to return multiple values from a function;
std::tuple<int,int> fun();
The result values can be used elegantly as follows:
int a;
int b;
std::tie(a,b)=fun();
Well, imho, the most important part is generic code. Writing generic code that works on all kinds of structs is a lot harder than writing generics that work on tuples. For example, the std::tie function you mentioned yourself would be very nearly impossible to make for structs.
this allows you to do things like this:
Store function parameters for delayed execution (e.g. this question )
Return multiple parameters without cumbersome (un)packing with std::tie
Combine (not equal-typed) data sets (e.g. from parallel execution), it can be done as simply as std::tuple_cat.
The thing is, it does not stop with these uses, people can expand on this list and write generic functionality based on tuples that is much harder to do with structs. Who knows, maybe tomorrow someone finds a brilliant use for serialization purposes.
I think most use for tuples comes from std::tie:
bool MyStruct::operator<(MyStruct const &o) const
{
return std::tie(a, b, c) < std::tie(o.a, o.b, o.c);
}
Along with many other examples in the answers here. I find this example to be the most commonly useful, however, as it saves a lot of effort from how it used to be in C++03.
I think there is NO good use for tuples outside of implementation details of some generic library feature.
The (possible) saving in typing do not offset the losses in self-documenting properties of the resulting code.
Substituting tuples for structs that just takes away a meaningful name for a field, replacing the field name with a "number" (just like the ill-conceived concept of an std::pair).
Returning multiple values using tuples is much less self-documenting then the alternatives -- returning named types or using named references. Without this self-documenting, it is easy to confuse the order of the returned values, if they are mutually convertible.
Have you ever used std::pair? Many of the places you'd use std::tuple are similar, but not restricted to exactly two values.
The disadvantages you list for tuples also apply to std::pair, sometimes you want a more expressive type with better names for its members than first and second, but sometimes you don't need that. The same applies to tuples.
The real use cases are situations where you have unnameable elements- variadic templates and lambda functions. In both situations you can have unnamed elements with unknown types and thus the only way to store them is a struct with unnamed elements: std::tuple. In every other situation you have a known # of name-able elements with known types and can thus use an ordinary struct, which is the superior answer 99% of the time.
For example, you should NOT use std::tuple to have "multiple returns" from ordinary functions or templates w/ a fixed number of generic inputs. Use a real structure for that. A real object is FAR more "generic" than the std::tuple cookie-cutter, because you can give a real object literally any interface. It will also give you much more type safety and flexibility in public libraries.
Just compare these 2 class member functions:
std::tuple<double, double, double> GetLocation() const; // x, y, z
GeoCoordinate GetLocation() const;
With a real 'geo coordinate' object I can provide an operator bool() that returns false if the parent object had no location. Via its APIs users could get the x,y,z locations. But here's the big thing- if I decide to make GeoCoordinate 4D by adding a time field in 6 months, current users's code won't break. I cannot do that with the std::tuple version.
Interoperation with other programming languages that use tuples, and returning multiple values without having the caller have to understand any extra types. Those are the first two that come to my mind.
I cannot comment on mirk's answer, so I'll have to give a separate answer:
I think tuples were added to the standard also to allow for functional style programming. As an example, while code like
void my_func(const MyClass& input, MyClass& output1, MyClass& output2, MyClass& output3)
{
// whatever
}
is ubiquitous in traditional C++, because it is the only way to have multiple objects returned by a function, this is an abomination for functional programming. Now you may write
tuple<MyClass, MyClass, MyClass> my_func(const MyClass& input)
{
// whatever
return tuple<MyClass, MyClass, MyClass>(output1, output2, output3);
}
Thus having the chance to avoid side effects and mutability, to allow for pipelining, and, at the same time, to preserve the semantic strength of your function.
F.21: To return multiple "out" values, prefer returning a struct or tuple.
Prefer using a named struct where there are semantics to the returned value. Otherwise, a nameless tuple is useful in generic code.
For instance, if returned values are value from the input stream and the error code, these values will not ego far together. They are not related enough to justify a dedicated structure to hold both. Differently, x and y pair would rather have a structure like Point.
The source I reference is maintained by Bjarne Stroustrup, Herb Sutter so I think somewhat trustworthy.

What is std::pair?

What is std::pair for, why would I use it, and what benefits does boost::compressed_pair bring?
compressed_pair uses some template trickery to save space. In C++, an object (small o) can not have the same address as a different object.
So even if you have
struct A { };
A's size will not be 0, because then:
A a1;
A a2;
&a1 == &a2;
would hold, which is not allowed.
But many compilers will do what is called the "empty base class optimization":
struct A { };
struct B { int x; };
struct C : public A { int x; };
Here, it is fine for B and C to have the same size, even if sizeof(A) can't be zero.
So boost::compressed_pair takes advantage of this optimization and will, where possible, inherit from one or the other of the types in the pair if it is empty.
So a std::pair might look like (I've elided a good deal, ctors etc.):
template<typename FirstType, typename SecondType>
struct pair {
FirstType first;
SecondType second;
};
That means if either FirstType or SecondType is A, your pair<A, int> has to be bigger than sizeof(int).
But if you use compressed_pair, its generated code will look akin to:
struct compressed_pair<A,int> : private A {
int second_;
A first() { return *this; }
int second() { return second_; }
};
And compressed_pair<A,int> will only be as big as sizeof(int).
std::pair is a data type for grouping two values together as a single object. std::map uses it for key, value pairs.
While you're learning pair, you might check out tuple. It's like pair but for grouping an arbitrary number of values. tuple is part of TR1 and many compilers already include it with their Standard Library implementations.
Also, checkout Chapter 1, "Tuples," of the book The C++ Standard Library Extensions: A Tutorial and Reference by Pete Becker, ISBN-13: 9780321412997, for a thorough explanation.
You sometimes need to return 2 values from a function, and it's often overkill to go and create a class just for that.
std:pair comes in handy in those cases.
I think boost:compressed_pair is able to optimize away the members of size 0.
Which is mostly useful for heavy template machinery in libraries.
If you do control the types directly, it's irrelevant.
It can sound strange to hear that compressed_pair cares about a couple of bytes. But it can actually be important when one considers where compressed_pair can be used. For example let's consider this code:
boost::function<void(int)> f(boost::bind(&f, _1));
It can suddenly have a big impact to use compressed_pair in cases like above. What could happen if boost::bind stores the function pointer and the place-holder _1 as members in itself or in a std::pair in itself? Well, it could bloat up to sizeof(&f) + sizeof(_1). Assuming a function pointer has 8 bytes (not uncommon especially for member functions) and the placeholder has one byte (see Logan's answer for why), then we could have needed 9 bytes for the bind object. Because of aligning, this could bloat up to 12 bytes on a usual 32bit system.
boost::function encourages its implementations to apply a small object optimization. That means that for small functors, a small buffer directly embedded in the boost::function object is used to store the functor. For larger functors, the heap would have to be used by using operator new to get memory. Around boost version 1.34, it was decided to adopt this optimization, because it was figured one could gain some very great performance benefits.
Now, a reasonable (yet, maybe still quite small) limit for such a small buffer would be 8 bytes. That is, our quite simple bind object would not fit into the small buffer, and would require operator new to be stored. If the bind object above would use a compressed_pair, it can actually reduce its size to 8 bytes (or 4 bytes for non-member function pointer often), because the placeholder is nothing more than an empty object.
So, what may look like just wasting a lot of thought for just only a few bytes actually can have a significant impact on performance.
It's standard class for storing a pair of values. It's returned/used by some standard functions, like std::map::insert.
boost::compressed_pair claims to be more efficient: see here
std::pair comes in handy for a couple of the other container classes in the STL.
For example:
std::map<>
std::multimap<>
Both store std::pairs of keys and values.
When using the map and multimap, you often access the elements using a pointer to a pair.
Additional info: boost::compressed_pair is useful when one of the pair's types is an empty struct. This is often used in template metaprogramming when the pair's types are programmatically inferred from other types. At then end, you usually have some form of "empty struct".
I would prefer std::pair for any "normal" use, unless you are into heavy template metaprogramming.
It's nothing but a structure with two variables under the hood.
I actually dislike using std::pair for function returns. The reader of the code would have to know what .first is and what .second is.
The compromise I use sometimes is to immediately create constant references to .first and .second, while naming the references clearly.
What is std::pair for, why would I use it?
It is just as simple two elements tuple. It was defined in first version of STL in times when compilers were not widely supporting templates and metaprogramming techniques which would be required to implement more sophisticated type of tuple like Boost.Tuple.
It is useful in many situations. std::pair is used in standard associative containers. It can be used as a simple form of range std::pair<iterator, iterator> - so one may define algorithms accepting single object representing range instead of two iterators separately.
(It is a useful alternative in many situations.)
Sometimes there are two pieces of information that you just always pass around together, whether as a parameter, or a return value, or whatever. Sure, you could write your own object, but if it's just two small primitives or similar, sometimes a pair seems just fine.