Consider this code:
#include <type_traits>
template < typename > struct BB { };
template < > struct BB<float> : BB<int> { };
struct DD : BB<float> { };
template < typename... Args >
void ff(BB<Args...>) { }
int main()
{
ff(BB<float>{});
ff(DD{}); // FAILS! 'BB<Args ...>' is an ambiguous base class of 'DD'
return 0;
}
The call of ff(DD{})
fails to compile, as gcc-8.3
doesn't want to pick one from BB<float>
and BB<int>
(clang
does the same). But BB<float>
isa BB<int>
, so why just BB<float>
can't be picked?!
The questions are: is this according to the standard and is there a workaround while defining ff
or BB
to help gcc-8.3
to pick BB<float>
?
This issue was the subject of CWG 2303. The committee decided to add wording "preferring 'nearer' base classes" and this wording was added to the working draft. So, in C++20, your example should instantiate ff<float>(BB<float>)
whereas in C++17, it is ambiguous.
Of course, the workaround if your compiler doesn't support "C++2a" mode or if C++2a mode hasn't implemented this change yet, is to add an overload of ff
that takes D
.
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