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