在 C++ 中使用 SFINAE 进行模板推导

template deduction with SFINAE in c++

本文关键字:SFINAE C++      更新时间:2023-10-16

我是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 中,它更喜欢模板函数,但是编译器在哪个阶段停止并抛出错误?

请明确解释编译器关于模板重载解析的处理阶段

但是为什么在版本1中,编译器会停止并抱怨?

template <typename T> void f(T t) { t.Crash(); } // version 1
void f(...) { } // The sink.
f(1);

在上述f的模板化版本中没有替换失败,因为可以从调用f(1)推断出Tint。根据重载解决规则,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);

那里存在替换失败,因为编译器需要在将T推断为int后推断出it的类型。它用int代替无效的int::iterator


关于函数的 SFINAE 在创建有效函数模板专用化的上下文中工作。

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(...)
}