以下声明使用了依赖于 SFINAE 的技术(替换失败不是错误):
// #3 : works only if (std::cerr << *x) works
template <typename T> auto dec (T* x) -> decltype(std::cerr << *x, 0);
// #4 : works for everything, but only if #3 fails
template <typename T> char dec (...);
考虑某种类型T
例如double
。然后是下面的代码,其中x
is a double*
:
std::cerr << *x;
会编译得很好,这意味着这段代码:
decltype(std::cerr << *x, 0);
格式良好,并且评估为int
。然后编译器会选择#3
when T
是一个可以这样使用的类型。
另一方面,如果T
是像一个vector<double>
,那么decltype
格式不正确(因为您无法流式传输vector
to cerr
),所以编译器别无选择,只能选择#4
.
上面的声明只是简单的帮助器,用于#12
and #13
. If T
是一种适用于#3
, then dec
返回类型为int
,并且匹配以下重载:
// #12
template <typename T> typename std::enable_if <sizeof dec <T> (0) != 1, view&>::type operator << (const T&);
because sizeof dec <T>
不会是1。
If T
效劳于#4
(因为它不起作用#3
), then dec
返回类型为int
,以及以下过载#13
已匹配:
// #13
template <typename T> typename std::enable_if <sizeof dec <T> (0) == 1, view&>::type operator << (const T&);
because sizeof dec <T>
正好是 1(a 的大小char
).
请注意,真正的区别在于如何#12
and #13
are defined。如果您看到定义,它们会处理以下情况T
是否可以适当地进行流式传输。