Planning to update my C++11 article

Pages: 12
Ages ago I wrote this:
http://www.cplusplus.com/articles/EzywvCM9/

I plan to update it, to include a couple more immediately useful features of C++11, such as lambdas... and of course to update the links and correct mistakes you point out.

I'm not sure if I should touch std::initializer_list or std::tuple, because the article is for beginners. What do you think, and what features should I write about?

Finally I hope the admin is still around, because I lost my login.
Add info on std::tuple. At least note that it has defined comparsion operators and demonstrate use of std::tie to quickly define comparsion operators for structs.
Please give an example, because I'm not sure what you mean.
For example we have struct
1
2
3
4
5
6
struct Person
{
    std::string lastName;
    std::string firstName;
    int age;
};
We need to define operator< which will order by last name, if they are same, by first name, and if are same too, by age (for sort or to insert it into set).
Using std::tie:
1
2
3
4
5
bool operator<(const Person& lhs, const Person& rhs)
{
    return std::tie(lhs.lastName, lhs.firstName, lhs.age) < 
           std::tie(rhs.lastName, rhs.firstName, rhs.age);
}

Without std::tie:
1
2
3
4
5
6
bool operator<(const Person& lhs, const Person& rhs)
{
    return ( lhs.lastName != rhs.lastName )? ( lhs.lastName < rhs.lastName ) :
           (lhs.firstName != rhs.firstName)? (lhs.firstName < rhs.firstName) :
                                             (   lhs.age    <    rhs.age   ) ;
}
(Of a bunch of if/else which will be even more complex)
Last edited on
Interesting. But why aren't you using std::make_tuple instead of std::tie?
If I understand the two functions correctly, std::make_tuple will copy the objects involved. [tt]std::tie[tt] will create a tuple of references (which is likely to be completely inlined.)
Well, it does seem to me that MiNiiPaa's suggestion is rather a misuse of std::tie(), which seems to have been intended to help extract values from tuples.

That said, this is what I wrote so far on tuples, and I'm still unsure if this section actually belongs in the article. If you have ideas to improve/shorten it, I'm listening.

Tuples
C++11 introduces std::tuple which is a generalization of std::pair.

Tuples can hold an arbitrary number of elements of different types and are supported by helper functions and relational operators. As such, tuples are a convenient replacement for classic POD (Plain Old Data) structures, and are ready to be used in sorting containers such as std::set.

Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <set>
#include <string>
#include <tuple>

// the C++03 way

struct Pod
{
    int i;
    char c;
    double d;
    std::string s;
};

Pod p;

p.i = 1;
p.c = 'c';
p.d = 0.1;
p.s = "Wauchope";

std::set<Pod> sp;

// sp.insert(p); // error, operator< overloaded for Pod is missing!

// the C++11 way

std::tuple<int, char, double, std::string> ticds;

ticds = std::make_tuple(1, 'c', 0.1, "Grizedale");
std::get<3>(ticds) = "Wauchope"; // change element at index 3

std::set<decltype (ticds)> st;

st.insert(ticds); // works out of the box!

// tuple test drive

std::tuple<int>                 ti      {21};
std::tuple<int, char>           tic     {22, 'A'};
std::tuple<int, char, float>    ticf    {23, 'B', 0.0f};

char c = std::get<1>(tic); // c == 'A'
int i;
float f = 0.5f;

std::tie(i, c, std::ignore) = ticf;
// i == 23
// c == 'B'
// f == 0.5f 


For the above example, Pod's missing operator< overload can be easily provided by using tuple's helper function std::tie, which is usually used to extract a tuple's elements. Here it will be used to construct a temporary tuple.

Because the return value of std::tie is a tuple, the default relational operators provided for std::tuple will kick in and do the remaining work for us.

Example:
1
2
3
4
bool operator < (const Pod &p1, const Pod &p2)
{
    return std::tie(p1.i, p1.c, p1.d, p1.s) < std::tie(p2.i, p2.c, p2.d, p2.s);
}

Catfish4 wrote:
Well, it does seem to me that MiNiiPaa's suggestion is rather a misuse of std::tie(), which seems to have been intended to help extract values from tuples.
o_O?? What makes you think this?
Also:
Tuples could be used whan you need to return > 2 values from function, but there is little sense to create struct for it. They are not replacement for POD, they relates to structs like lambdas to functions.

There is neat but rarely used and maybe obscure trick:
std::tie(a, b, c, d) = std::make_tuple(b, c, d, a);
I prefer bunch of assigment to not confuse anybody who will read my code.


std::tie creates a tuple of l-value references. It is used when you need to make use of assignment operator (expract values from tuple), to avoid copy of large object (my example, instead of make_tuple), or when you need a tuple of references.
Last edited on
I guess "misuse" wasn't the right word for this.

MiNiiPaa used std::tie() to construct temporary tuples just to simplify the overloading of operator< for a structure, while std::tie() seems designed for multiple element extraction.
rarely used and maybe obscure trick:

I've seen various tie() tricks all over the place ever since boost::tuple appeared.
Last edited on
Writing std::tie( a, b, c ) is simpler (and potentially a bit more efficient) than
std::make_tuple( std::ref(a), std::ref(b), std::ref(c) )

With make_tuple, std::make_tuple( std::ref(a), std::ref(b), std::cref(c) ) is possible;
and with tie std::tie( a, b, std::ignore, d ) is possible.

std::tie(), std::make_tuple() or std::forward_as_tuple() could be the most useful construct depending on the particular use-case.
Does anybody have more comments or corrections for the article section I have posted above?

It was suggested that tuples aren't a replacement for POD. All right, then I would appreciate a better introduction so as to answer the readers' possible "why would I bother using tuples?" question.
IMHO, don't try to cover everything - for instance tuples can wait.
But highlight features which are the most immediately useful for beginners,
would encourage them to use better idioms:

In addition to what is already there:

Smart pointers (do not use raw owning pointers).
Lambda expressions, (may be) std::function<> and std::bind<>().
New integer types.
Static assertions.
nullptr.
Uniform initialization and in-class member initializers.
Some algorithms all_of/any_of/none_of, copy_if ...
Useful functions llround, to_string, stoul ...

(Based on forum faqs) Random number generators, Time utilities
Last edited on
to take it on an incidental off-topic tangent (it's a lounge anyway), it kind of irks me when so many people talk about C++11 features as something novel.

Tuples have been commonplace for at least 13 years, since the post-99 explosion of typelists. TR1/C++11 just picked one particularly popular version and made it a requirement.

Case in point: my corporate infrastructure library has typelists but no tuples (although it's "in progress" finally), and I am seeing over 6000 source files in the codebase that use tuples from a handful of different implementations, written by various application programmers, on as-needed basis.
Catfish4 wrote:
std::tie() seems designed for multiple element extraction.
I still don't understand what makes you think this. Nevermind, I just wasn't thinking properly. I see what you mean now.
Last edited on
Anybody here using constexpr? It looks like yet another manual optimization keyword, for use by experts, just like restrict in C99.
I haven't had the chance to use it yet because all my constants are loaded from config files.
It looks like yet another manual optimization keyword, for use by experts, just like restrict in C99.
constexpr functions can be called in runtime too. They just will aggressively try to make most calculation in compile time.
Constexpr values will be substituted by value in places where they are referenced (like inline for variables). If with const compiler can substiute values (and if we remove constness later it should not), with constexpr it should do that.
1
2
3
4
5
6
7
int main()
{
    constexpr int x = 2;
    const int* a = &a; //I have doubts if pointer to constexpr variable is standard conformant.
    std::cin >> const_cast<int&>(x); 
    std::cout << x << ' ' << *a; //x will be replaced by 2, a will point to changed value of x
}
input: 5
output: 2 5

In C++14 many limitations of constexpr functions will be removed and maybe way to provide different implementation of constexpr function to use in runtime (as constexpr implementation usually slow)

I do not think that constexpr is good for the beginner article.
http://www.codeproject.com/Articles/570638/Ten-Cplusplus11-Features-Every-Cplusplus-Developer Found out interesting article on C++11. You might pick something from it.
Pages: 12