C++中模板函数=delete与explicit修饰成员函数的区别是什么
两种写法的核心差异与原理说明
1. 第二种写法本身属于非法C++语法
explicit关键字的适用场景只有两类:
- 修饰类的构造函数,避免该构造函数被用于隐式类型转换
- 修饰用户自定义的类型转换函数,避免该转换被隐式调用
它不能用于修饰普通成员函数,你写的explicit void f(double d);会直接被编译器报语法错误,完全无法达到你想要的「禁止参数隐式转换」的效果。
2. 模板=delete写法的工作逻辑
第一种写法是C++11及以后标准下,实现「仅接受某一特定类型参数、禁止所有隐式转换」的标准实现,原理如下:
- 当传入参数的类型严格为
double时,重载决议会优先匹配非模板的void f(double d),函数正常调用 - 当传入其他任意类型的参数时(哪怕该类型可以隐式转换为
double,比如int、float、long等),模板函数template<class T> void f(T)会实例化出对应类型的重载,重载决议的优先级高于需要做隐式类型转换的非模板函数,而该模板函数被标记为=delete,编译器会直接抛出调用已删除函数的错误,刚好实现了禁止隐式转换的需求。
举个实际调用的例子:
OnlyDouble od; od.f(1.0); // 正常调用,参数为double od.f(1); // 编译报错,匹配到删除的f<int>(int) od.f(1.0f); // 编译报错,匹配到删除的f<float>(float)
3. 补充说明
如果你使用的是C++20及以上标准,也可以用concept实现等价效果,写法更简洁:
struct OnlyDouble { void f(std::same_as<double> auto d); };
效果和第一种模板=delete的写法完全一致。
内容的提问来源于stack exchange,提问作者heretoinfinity
相关产品推荐
相关产品推荐

