After being confused why my code gave me an ambiguity error on GCC but no errors on Clang, I simplified the code. It can be seen below.
struct Foo
{
// Foo(Foo&&) = delete;
// Foo(const Foo&) = delete;
Foo(int*) {}
};
struct Bar
{
template<typename T>
operator T()
{
return Foo{nullptr};
}
};
int main() { Foo f{Bar{}}; }
The errors are as follows.
main.cpp:17:18: error: call to constructor of 'Foo' is ambiguous
int main() { Foo f{Bar{}}; }
^~~~~~~~
main.cpp:1:8: note: candidate is the implicit move constructor
struct Foo
^
main.cpp:1:8: note: candidate is the implicit copy constructor
main.cpp:5:1: note: candidate constructor
Foo(int*) {}
^
I was unable to make it successfullycompile for Clang this time, so I suppose that was just a Clang bug and this is the intended behavior.
When I explicitly delete the copy and move constructors (i.e. uncomment the top two lines of code), I instead get
note: candidate constructor has been explicitly deleted
but still an error. How would I go about disambiguating the construction here, then?
Note that I specifically added the Foo{nullptr}
instead of just nullptr
, but there is no difference. Same with marking the Foo
ctor explicit. This ambiguity error only occurs when Bar
's conversion operator is templated.
I can add some SFINAE to the conversion operator, but I am unsure of what I would exclude. For example, this would make it work:
template<typename T, std::enable_if_t<std::is_same<T, Foo>{}>* = nullptr>
This is another one that I found and this might be my answer:
template<typename T, std::enable_if_t<!std::is_same<T, int*>{}>* = nullptr>