Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template argument deduction for inheriting specializations

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>?

like image 949
Vahagn Avatar asked Aug 16 '19 18:08

Vahagn


1 Answers

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.

like image 126
Brian Bi Avatar answered Oct 24 '22 00:10

Brian Bi