根据SFINAE对cpprefence的描述
只有函数类型或其模板参数类型或其显式说明符 (C++20 起)的直接上下文中的类型和表达式中的失败是 SFINAE 错误。如果对替换类型/表达式的评估导致副作用,例如某些模板特化的实例化、隐式定义的成员函数的生成等,则这些副作用中的错误将被视为硬错误。
特别是,当Helper<T>
我在下面的代码中在模板参数推导期间实例化时,正如预期的那样,我收到错误。所以这是我的问题:为什么std::enable_if
SFINAE 可以很好地工作,即使它是一个必须实例化的结构(并且通常与许多也在此过程中实例化的类型特征结构一起使用)。
这是代码
#include<iostream>
#include<type_traits>
template<typename T, typename U = typename T::my_type>
void sfinae(const T&) { std::cout << "template\n"; }
void sfinae(...) { std::cout << "non template\n"; }
template<typename T>
struct Helper{
using my_type = typename T::my_type;
};
template<typename T, typename U = typename Helper<T>::my_type>
void hardError(const T&) { std::cout << "template\n"; }
void hardError(...) { std::cout << "non template\n"; }
struct NonEmpty{ using my_type=int; };
struct Empty{ };
int main()
{
NonEmpty ne;
Empty e;
sfinae(ne); //template overload called
hardError(ne); //template overload called
sfinae(e); //non-template overload called
hardError(e); //hard error
}
可能的实现std::enable_if
是
template <bool cond, typename T = void> struct enable_if;
template <typename T> struct enable_if<false, T>{};
template <typename T> struct enable_if<true, T>{ using type = T; };
所以enable_if
不会产生硬错误。实例化std::enable_if<false>
是有效的。
实例化Helper<Empty>
会在 上产生错误Empty::type
,这不是在SFINAE 的直接上下文中完成的,因此是硬错误。
std::enable_if
并且std::void_t
与 SFINAE 配合得很好,因为它们提供了在直接上下文中失败的简单方法:
std::enable_if<cond_v<T>, int>::type = 0
或typename AlwaysVoid = std::void_t<decltype(dependent_expression)>
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句