Inspired by this answer, I tried next example :
#include <map>
#include <string>
#include <iostream>
int main()
{
const std::map< int, std::string > mapping = {
1, "ONE",
2, "TWO",
};
const auto it = mapping.find( 1 );
if ( mapping.end() != it )
{
std::cout << it->second << std::endl;
}
else
{
std::cout << "not found!" << std::endl;
}
}
and the compilation failed with next error message (g++ 4.6.1) :
gh.cpp:11:5: error: could not convert '{1, "ONE", 2, "TWO"}' from '<brace-enclosed initializer list>' to 'const std::map<int, std::basic_string<char> >'
I know how to fix it :
const std::map< int, std::string > mapping = {
{1, "ONE"},
{2, "TWO"},
};
but why the compilation fails in the top example?
Because the map is a non-aggregate, and contains non-aggregate elements (std::pair<key_type, mapped_type>
), so it requires an initializer-list full of initializer-lists, one for each pair.
std::pair<int,int> p0{ 1,2 }; // single pair
std::map<int, int> m { { 1,2 } }; // map with one element
std::map<int, int> m { { 1,2 }, { 3,4} }; // map with two elements
Bear in mind that the rules for brace elision apply to aggregates, so they do not apply here.
The C++11 standard allows braces to be elided only when the target is an aggregate:
8.5.1 Aggregates [dcl.init.aggr]
An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no brace-or-equal- initializers for non-static data members (9.2), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).
...
(Paragraph 11)
In a declaration of the form
T x = { a };
braces can be elided in an initializer-list as follows. If the initializer-list begins with a left brace, then the succeeding comma-separated list of initializer-clauses initializes the members of a subaggregate; it is erroneous for there to be more initializer-clauses than members. If, however, the initializer-list for a sub- aggregate does not begin with a left brace, then only enough initializer-clauses from the list are taken to initialize the members of the subaggregate; any remaining initializer-clauses are left to initialize the next member of the aggregate of which the current subaggregate is a member.
Been a long time since I've done C++, but my guess would be because std::map
is expecting a set of individual objects, each object containing a key and a value pair.
Having a single list of individual items doesn't make sense, and it's also difficult to read (to make sure that you have a number of items that is exactly divisible by two).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With