在 C++ 中使用 SFINAE 进行模板推导
template deduction with SFINAE in c++
我是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)
推断出T
int
。根据重载解决规则,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(...)
}
相关文章:
- 为什么使用SFINAE而不是函数重载
- 如何使用模板函数的函数签名进行SFINAE
- 数据成员SFINAE的C++17测试:gcc vs clang
- 使用在用于SFINAE的void_t中具有参数的方法
- 编译器如何在使用SFINAE的函数和标准函数之间确定两者是否可行
- 提供与TMP和SFINAE的通用接口
- "Inverse SFINAE"避免模棱两可的过载
- 表达式 SFINAE:如何根据类型是否包含具有一个或多个参数的函数来选择模板版本
- 如何在儿童类中使用SFINAE
- 使用 SFINAE 作为模板参数的编译时递归
- 使用 SFINAE 设计模板方法
- 与SFINAE支票交朋友
- C++许多 SFINAE 风格的过载
- 是否可以混合使用SFINAE和模板专业化?
- C++表达SFINAE和ostream操纵器
- SFINAE不能防止模棱两可的操作员过载吗?
- SFINAE是否取决于类型推断?
- MSVC 无法编译 SFINAE 检查
- SFINAE 检查模板参数运算符
- SFINAE 与 numeric_limits<T>::max() 在 MSVC2017 上