函数调用禁止隐式转换
很多开发者写代码的时候经常会有一个想法,就是我写了一个函数,我希望调用方传递的参数必须完全符合形参类型,而不是隐式转换。但是又觉得禁用所有其它的隐式转换又非常的麻烦懒得弄。我们提供一个简单的方法。
cpp
void f(int);
cpp
void f(int){}
struct X{
operator int()const { return 0; }
};
struct Y {
operator double()const { return 0.; }
};
int main(){
f(1); // int
f(1u); // unsigned int
f(1l); // long
f(1ll); // long long
f(1lu); // unsigned long
f(1llu); // unsigned long long
f(1.); // double
f(1.f); // float
f('c'); // char
f(std::uint8_t{}); // unsigned char
f(std::int8_t{}); // signed char
f(X{}); // X
f(Y{}); // Y
}
一切可以隐式转换到 int 以及转换到可以转换为 int 类型的类型,都能够调用函数
f
,所以是无数种。测试。
但是我们只想让 f(1)
成立,这很简单,加一段代码:
cpp
template<typename T>
void f(T) = delete;
原理也很简单,我们定义了一个重载函数模板 f
,并且把它定义为弃置的。如果我们使用 f(1)
,那么重载决议会选择到我们的非模板的函数 f
。如果不是 f(1)
,即不是传入的 int 类型,那么重载决议就会选择到模板函数 f
。然而如果弃置函数真的被选择,那会产生一个编译错误。
如果支持 C++20 我们还可以使用简写函数模板,更加简单:
cpp
void f(auto) = delete;