默认模板参数和偏特化
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 {};
我正在尝试了解使用默认参数的部分模板特化。如果我在 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 {};