-
March 20th, 2012, 05:36 AM
#1
pair vs tuple in uniform initialization
I'm having some problems coping with this "uniform initialization"/"initialization list" example from Bjarne Stroustrup himself.
What bothers me is that the example does not work with tuples:
Code:
#include <string>
#include <list>
#include <tuple>
#include <utility>
//This works: Uniform initialization, normal
std::pair<std::string, std::string> a{"Nygaard","Simula"};
std::tuple<std::string, std::string> b{"Richards","BCPL"};
//This doesn't work, initialization lists, normal
//std::pair<std::string, std::string> aa{{"Nygaard","Simula"}};
//std::tuple<std::string, std::string> bb{{"Richards","BCPL"}};
//This works
std::list<std::pair<std::string, std::string>> languages_pair = {
{"Nygaard","Simula"}, {"Richards","BCPL"}, {"Ritchie","C"}
};
//but this doesn't
std::list<std::tuple<std::string, std::string>> languages_tuple = {
{"Nygaard","Simula"}, {"Richards","BCPL"}, {"Ritchie","C"}
};
int main()
{ }
I can't understand why the tuple example is not working :/
Which constructor are the pairs using that the tuple doesn't have?
Is your question related to IO?
Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.
-
March 20th, 2012, 08:16 AM
#2
Re: pair vs tuple in uniform initialization
Hi,
the constructor tuple::tuple(P1, P2, ...PN) is explicit.
Code:
std::tuple<std::string, std::string> b{"Richards","BCPL"};
Here you are explicitly calling the constructor.
Code:
std::list<std::tuple<std::string, std::string>> languages_tuple = {
{"Nygaard","Simula"}, {"Richards","BCPL"}, {"Ritchie","C"}
};
Here you are trying to implicitly call the constructor which is not allowed.
As opposed to that, std::pair::pair(const Type1& __Val1, const Type2& __Val2); is not explicit.
More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason - including blind stupidity. --W.A.Wulf
Premature optimization is the root of all evil --Donald E. Knuth
Please read Information on posting before posting, especially the info on using [code] tags.
-
March 20th, 2012, 10:40 AM
#3
Re: pair vs tuple in uniform initialization
adding to treuss post, note that as in c++03 there are direct and copy intializations, in c++11 there are also direct and copy list-initializations. That is, an initialization of the form "= { ... }" requires copy-initialization semantics for all the set of braces recursively and not just the outermost one. So, in the code
Code:
std::list<std::tuple<std::string, std::string>> languages_tuple = { {"Nygaard","Simula"}, {"Richards","BCPL"}, {"Ritchie","C"} };
the outermost braces match to list::list(initializer_list<tuple<string,string>>), and the innermost braces sets would match to a non-explicit ( because of the copy-list-initialization ) converting tuple<string,string>(?) constructor that does not exist, hence the error.
Maybe, your question stemmed from you trying to recover the initialization mechanism through the std::list ctor only; note that from the list pov the initialization is "legal", as in the c++03 code:
Code:
#include <vector>
std::vector<int> v1;
std::vector<std::vector<int>> v2(v1.begin(),v1.end()); // invokes an explicit ctor
so there would be no problem to initialize the list through an explicit converting costructor of tuple because the list initializer list ctor is equivalent to the iterator range ctor in the obvious way; the expected behavior is enforced by an ad hoc rule triggered by the copy-initialization context.
For example, the following nearly equivalent code should ( see below ) compile
Code:
std::initializer_list<std::tuple<std::string, std::string>> il{
{"Nygaard","Simula"}, {"Richards","BCPL"}, {"Ritchie","C"}
};
std::list<std::tuple<std::string, std::string>> languages_tuple = il;
unfortunately, I've no initializer list supporting compiler at my disposal , so, I'll leave it as a conjecture ...
-
March 20th, 2012, 11:14 AM
#4
Re: pair vs tuple in uniform initialization
Hum... explicit multi-variable constructors...
Thanks
Is your question related to IO?
Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.
-
March 20th, 2012, 11:36 AM
#5
Re: pair vs tuple in uniform initialization
Originally Posted by superbonzo
...
Thanks for the info. I'm getting a better hand at the notion of initializer list, and brace enclosed intialization. They can be confusing if you try to "learn by typing" rather than learn by actually reading a book. I think I get it now though.
It was the explicit on a double argument constructor that threw me off. The example you gave didn't compile, not because of the initiaizer list, but because the compiler can't build the tuple. It's nothing a bit of explicit can't solve:
Code:
std::list<std::tuple<std::string, std::string>> il{
std::tuple<std::string, std::string>{"Nygaard","Simula"},
std::tuple<std::string, std::string>{"Richards","BCPL"},
std::tuple<std::string, std::string>{"Ritchie","C"}
};
I must say that while I am a fan of the tuples, I hate the amount of text they take to write (I hate using "using"). The fact that they are explicit, and that make_tuple builds a tuple of the wrong type end up making their use (here) especially verbose.
No a big deal, but it doesn't quite have the elegance of the first exemple
Is your question related to IO?
Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.
-
March 20th, 2012, 12:13 PM
#6
Re: pair vs tuple in uniform initialization
Originally Posted by monarch_dodra
The example you gave didn't compile
can you post the compiler output ?
so, in the direct-list-initialization case only the outermost braces can match an explicit constructor ... that is, inner braces are always considered copy initializations. Ok, it makes sense, but I would also have liked a way of direct-initializing in a "nested" way ...
-
March 20th, 2012, 12:26 PM
#7
Re: pair vs tuple in uniform initialization
Originally Posted by superbonzo
can you post the compiler output ?
Sorry, should have posted it right from the beginning:
Code:
main.cpp|error: converting to 'std::tuple<std::basic_string<char>, std::basic_string<char> >' from initializer list would use explicit constructor 'std::tuple<_T1, _T2>::tuple(_U1&&, _U2&&) [with _U1 = const char (&)[8], _U2 = const char (&)[7], _T1 = std::basic_string<char>, _T2 = std::basic_string<char>]'|
This is what I get in both my first example, and with your code.
MinGW 4.6.2.
Is your question related to IO?
Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|