这个问题可能很难用标题中的句子来描述,但这里有一个最小的例子:
#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;
}
(也可在 Godbolt 上使用 https://godbolt.org/z/VE6ARX)
基本上,我们有一个基本模板类my_trait
采用两种类型(以及用于专业化目的的虚拟类型),具有两个部分专业化:
- 当两种类型相同时
- 当这两种类型都是实例化时
temped
相同类型的类模板
天真地,我们期望第二个部分专业化不会与第一个部分专业化产生歧义,因为它感觉“更专业化”,对推导的类型施加更多限制T
and U
在基本模板上。
然而主要编译器似乎都同意我们的期望是错误的:为什么不认为它更专业?