16

I have the following code:

#include <initializer_list>
#include <utility>

enum class Classification
{
  Unspecified,
  Primary,
  Secondary
};

class ClassificationMap
{
public:
  ClassificationMap(std::initializer_list<std::pair<const Classification, int>> content = {});
};

void foo(ClassificationMap) {}

int main()
{
    foo({{Classification::Unspecified, 42}});
}

Visual Studio 2013 & 2017 and Clang 3.4.1 (and above) both compile the code just fine. From my POV, it should be fine as well. However, GCC 5.1 refuses to compile it, with the following error:

<source>: In function 'int main()':
<source>:22:44: error: could not convert '{{Unspecified, 42}}' from '<brace-enclosed initializer list>' to 'ClassificationMap'
     foo({{Classification::Unspecified, 42}});

[Live example]

(I am passing the correct standard flag (-std=c++11) to both GCC and Clang).

Is there a problem in my code, or is this actually a GCC bug?


Supplemental info: in my real code, the initialiser list is used to initialise an unordered map member of the ClassificationMap class (that's why its type is what it is). I need the code to work in VS2013 & GCC 5.1

9
  • 4
    Adding another set of {} around them makes it work. Very strange indeed... Commented May 5, 2017 at 12:44
  • 4
    Also, removing = {} in ClassificationMap(std::initializer_list<std::pair<const Classification, int>> content = {}) gets it to compile in g++ Commented May 5, 2017 at 12:46
  • 1
    Weirdly enough, this fixes it too: foo(std::initializer_list<std::pair<const Classification, int>>{{Classification::Unspecified, 42}}); It seems that gcc fais to correctly deduce the type of std::initializer_list. Clang handles it just fine. Commented Jun 4, 2017 at 14:50
  • 1
    Did you tell gcc to use the right C++ standard? e.g. -std=c++11? Commented Sep 1, 2017 at 19:16
  • 3
    I think the problem is that you cannot convert a brace-enclosed initialization list to a std::pair (there's no such contructor), which is what the ClassificationMap constructor takes. The extra braces "solve" the problem because that direct-list-initializes the whole thing. Commented Sep 4, 2017 at 10:00

1 Answer 1

1

Here is a good workaround for the issue (abandon default value):

class ClassificationMap
{
public:
    ClassificationMap(std::initializer_list<std::pair<const Classification, int>> content);
    ClassificationMap() : ClassificationMap({}) {}

};

You will have exact behavior you want and it compiles everywhere.

https://godbolt.org/g/WUuMzP

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.