struct b_symbol { tem...">

Gcc fails: "overload call is ambiguous", while clang doesn't

I have the following code:

#include <experimental/string_view> struct b_symbol { template <typename T> explicit b_symbol(T&& symbol) : symbol(std::forward<T>(symbol)) { } std::experimental::string_view symbol; }; struct b_utf8 { template <typename T> explicit b_utf8(T&& value) : value(std::forward<T>(value)) { } std::experimental::string_view value; }; struct value { explicit value(b_utf8) {} explicit value(b_symbol) {} }; int main() { value v({b_utf8("test")}); } 

You can try it on godbolt .

If I compile it with clang (3.8.0):
clang++ oload.cpp -std=c++1y
everything is working fine.

If I compile it with gcc (6.1.1 20160602)
g++ oload.cpp -std=c++1y
I get:

 oload.cpp: In function 'int main()': oload.cpp:30:29: error: call of overloaded 'value(<brace-enclosed initializer list>)' is ambiguous value v({b_utf8("test")}); ^ oload.cpp:25:14: note: candidate: value::value(b_symbol) explicit value(b_symbol) {} ^~~~~ oload.cpp:24:14: note: candidate: value::value(b_utf8) explicit value(b_utf8) {} ^~~~~ oload.cpp:23:8: note: candidate: constexpr value::value(const value&) struct value { ^~~~~ oload.cpp:23:8: note: candidate: constexpr value::value(value&&) 

Why is this a difference?
Is gcc behavior right?

EDIT: As Slavanap noted in his answer, the error can be circumvented by removing curly braces on the call site. However, I would like to know why compilers behave differently.

+5
source share
2 answers

You pass an initialization list to a constructor that explicitly accepts either b_utf8 or b_symbol, and is not correct.

You must define a constructor that takes an initialization list if you do not want to use implicit casts.

I think this happens during the change process for C ++ 17, and you will be allowed to do this as clang.

EDIT: Interesting

 struct b_utf8 { b_utf8() = default; //b_utf8(){} }; struct value { explicit value(b_utf8) {} }; int main() { value v({b_utf8()}); } 

compiles but

 struct b_utf8 { //b_utf8() = default; b_utf8(){} }; struct value { explicit value(b_utf8) {} }; int main() { value v({b_utf8()}); } 

cannot overload. I am not sure why, as far as I can tell, the permission of an overload should behave the same in these two cases.

+1
source

The error says <brace-enclosed initializer list> .

  // Why not just try to call value v(b_utf8("test")); // instead value v({b_utf8("test")}); // ? 
0
source

All Articles