默认模板参数和偏特化

Default template paramters and partial specialization

我正在尝试了解使用默认参数的部分模板特化。如果我在 is_comparable 专业化中删除对 void 的转换,则打印的值始终为 false,而如果我保持对 (void) 的转换,则一切正常。有人可以解释为什么需要转换为 void 吗?它可能与匹配 T3 的默认模板参数有关,但我试图在这里获得一些额外的见解,以了解模板部分特化和默认模板参数的注意事项。

template<typename T1, typename T2, typename T3 = void>
struct is_comparable
{
 static const bool value = false;
};

template<typename T1, typename T2>
struct is_comparable<T1, T2, decltype((void)(std::declval<T1>() == std::declval<T2>()))>
{
  static const bool value = true;
};

int main()
{
   cout << boolalpha;
   cout << is_comparable<int, char>::value << endl;
   cout << is_comparable<int, float *>::value << endl;
}

更新:即使使用指针,我也观察到相同的行为。我假设在这种情况下会选择部分专业化?

template<typename T1, typename T2, typename T3 = void>
struct is_comparable
{
 static const bool value = false;
};

template<typename T1, typename T2>
struct is_comparable<T1*, T2*, decltype((std::declval<T1>() == std::declval<T2>()))>
{
  static const bool value = true;
};

int main()
{
   cout << boolalpha;
   cout << is_comparable<int*, int*>::value << endl;
}

编译器实例化主模板并得到以下内容:

is_comparable<int, char, void>

然后,为了 select 最佳匹配,它会尝试实例化您的特化(假设没有类型转换 void 并假设类型替换成功)并获取以下类型:

is_comparable<int, char, bool>

它根本匹配主模板,所以它不能是更好的匹配。

我们默认使用主模板,所以

  • is_comparable<int, char>is_comparable<int, char, void>
  • is_comparable<int, float *>is_comparable<int, float*, void>
  • is_comparable<int*, int*>is_comparable<int*, int*, void>

现在,你没有 void cast 的专业化大部分是(除非 operator== 的特殊重载)是

  • is_comparable<T1, T2, bool /* with SFINAE */>

因此与预期参数不匹配。 你必须使用:

  • is_comparable<int, char, bool>
  • is_comparable<int, float *, bool>
  • is_comparable<int*, int*, bool>

转换为 void 的另一种方法是 std::void_t:

template<typename T1, typename T2, typename Enabler = void>
struct is_comparable : std::false_type {};

template<typename T1, typename T2>
struct is_comparable<T1, T2,
                     std::void_t<decltype(std::declval<T1>() == std::declval<T2>())>>
    : std::true_type {};