为什么匹配模板类上的部分类模板特化与另一个没有模板匹配的部分专业模棱两可?

Ad *_*d N 6 c++ templates sfinae template-specialization

这个问题可能很难在标题中的句子中描述,但这是一个最小的示例:

#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;    
}
Run Code Online (Sandbox Code Playgroud)

在godbolt上也可用

基本上,我们有一个基本模板类,my_trait它有两种类型(为了专业化目的,还有一个虚拟类型),有两个部分专业化:

  • 当两种类型相同时
  • 当两种类型都实例化temped相同类型的类模板时

天真地,我们希望第二个局部专业化不会与第一个局部专业化模棱两可,因为它感觉“更加专业化”,从而对推导类型TU基本模板施加了更多限制。然而,主要的编译器似乎同意我们错了我们的期望:为什么不认为它更专业?

Yam*_*ari 0

这是因为

std::enable_if_t<std::is_same_v<temped<int>, temped<int>> 
Run Code Online (Sandbox Code Playgroud)

解决无效然后你有

my_trait<temped<int>, temped<int>, void>::value 
Run Code Online (Sandbox Code Playgroud)

模糊地定义为真或假。如果您将enable_if解析的类型更改为bool,那么一切都会编译良好