Why is a partial class template specialization on a matching template class ambiguous with another partial specialization without the template match?

蓝咒 提交于 2019-12-09 12:46:18

问题


The question may be too hard to describe in on sentence in the title, but here is a minimal example:

#include <iostream>
#include <type_traits>

template <class T, class U, class Enabler>
struct my_trait : std::false_type
{};

template <class T, class U>
struct my_trait<T, U, 
                std::enable_if_t<std::is_same<T, U>::value>> : std::true_type
{};

template <class T>
class temped
{};

template <class T>
struct my_trait<temped<T>, temped<T>, void> : std::false_type
{};

template <class T, class U>
using trait_t = my_trait<T, U, void>;

int main()
{
    std::cout << std::boolalpha;
    std::cout << trait_t<int, float>::value << std::endl;   // false
    std::cout << trait_t<int, int>::value << std::endl;     // true

    // Compilation error: Ambiguous
    //std::cout << trait_t<temped<int>, temped<int>>::value << std::endl;
    return 0;    
}

(also available on godbolt)

Basically, we have a base template class my_trait taking two types (and a dummy type for specialization purposes), with two partial specializations:

  • When the two types are the same
  • When the two types are instantiation of the temped class template for the same type

Naïvely, we would have expected the second partial specialization not to be ambiguous with the first, as it feels "more specialized", putting more restriction on the deduced types for T and U on the base template. Yet major compilers seems to agree that we were wrong with our expectations: why is it not considered more specialized?


回答1:


it's because

std::enable_if_t<std::is_same_v<temped<int>, temped<int>> 

resolves to void and then you have

my_trait<temped<int>, temped<int>, void>::value 

defined ambigiously as true or false. If you change the type enable_if resolves to, let's say bool, everything compiles fine




回答2:


@super's now-deleted answer got this basically right. std::enable_if_t<...> is not void in partial ordering; as a dependent type it can in principle be something completely arbitrary. It effectively is considered a completely unique type for partial ordering purposes.

As a result of this mismatch, the deduction during partial ordering fails in both directions, and the specializations are ambiguous.



来源:https://stackoverflow.com/questions/58960177/why-is-a-partial-class-template-specialization-on-a-matching-template-class-ambi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!