I'm encountering an unexpected issue in some code I'm writing now and I'm not sure which compiler is correct.
We have a multi-argument constructor which takes const char*, const char*
, but it is declared explicit:
constexpr explicit Wrapper(const char* a, const char* b) : pair(a,b){}
And then we have a function which takes Wrapper
and an overload which takes a std::pair<const char*, const char*>
void q(Wrapper w);
void q(std::pair<const char *, const char *> w);
And then we have code like this, which I would expect to call the second overload:
q({"a", "b"});
This compiles fine on clang, but fails to compile on both GCC and MSVC. I've been trying to look for any mention of explicit multi-arg constructor in the standard and if there's anything mentioning this ambiguity but I haven't found the relevant text. I'm just wondering which behavior is correct and which is wrong?
godbolt link: https://godbolt.org/g/2aYUov
Using your provided constructor for Wrapper, g++ 7.1.1 gives me the following error:
main.cpp: In function ‘int main()’:
main.cpp:29:25: error: converting to ‘Wrapper’ from initializer list would use explicit constructor ‘constexpr Wrapper::Wrapper(const char*, const char*)’
Wrapper w({"a", "b"});
^
So it seems that the explicit keyword on the Wrapper constructor is well taken into account when manually triggering a conversion.
However, the error on the call to q seems to indicate that overload resolution is ignoring the explicit keyword:
main.cpp:34:17: error: call of overloaded ‘q(<brace-enclosed initializer list>)’ is ambiguous
q({"a", "b"});
^
main.cpp:16:6: note: candidate: void q(Wrapper)
void q(Wrapper w)
^
main.cpp:21:6: note: candidate: void q(std::pair<const char*, const char*>)
void q(std::pair<const char *, const char *> w)
^
This could be a bug in g++, which would need to be verified with other sources.
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