我是SFINAE的新手。我注意到了:
template <typename T> void f(T t) { t.Crash(); } // version 1
void f(...) { } // The sink.
f(1);
template <typename T> void f(const T& t, typename T::iterator* it = nullptr) { } // version 2
void f(...) { } // The sink.
f(1);
在版本2中,由于SFINAE,它不会抛出任何错误,并选择椭圆接收器。但为什么在版本1,编译器会停止并抱怨?
SFINAE仅适用于签名而非身体吗?所以在版本1中,它更喜欢模板函数,但是在什么阶段编译器会停止并抛出错误?
请明确说明编译器关于模板重载解析的处理阶段。
答案 0 :(得分:4)
但为什么在版本1,编译器会停止并抱怨?
template <typename T> void f(T t) { t.Crash(); } // version 1
void f(...) { } // The sink.
f(1);
上面f
的模板化版本中没有替换失败,因为T
可以从调用int
推断为f(1)
。根据重载决策规则,f<int>(int)
比f(...)
template <typename T> void f(const T& t, typename T::iterator* it = nullptr) { } // version 2
void f(...) { } // The sink.
f(1);
那里存在替换失败,因为在将it
推导为T
之后,编译器需要推导出int
的类型。它会替换int
代替无效的int::iterator
。
SFINAE on函数适用于创建有效的功能模板专业化的上下文。
SFINAE仅适用于签名而非身体吗?
你可以这样说......在这些有效的代码示例中获取战利品:
//Just the declaration
template <typename T>
void f(T t);
void f(...);
int main(){
f(1); //selects f<int>(int)
}
同时
//just the declarations.
template <typename T>
void f(const T& t, typename T::iterator* it = nullptr);
void f(...);
int main(){
f(1); //selects f(...)
}