防止从false到指针的静默强制转换

Prevent silent cast from false to pointer

本文关键字:静默 转换 指针 false      更新时间:2023-10-16

我有一个函数

void foo(int *bar)
{}

如果我这样调用foo:,Visual Studio 2012现在将愉快地编译,并且没有警告

int main()
{
foo(false);
return 0;
}

然而,如果我将foo(false)更改为foo(true),我会得到一个错误:

1>main.cpp(132): error C2664: 'foo' : cannot convert parameter 1 from 'bool' to 'int *'
1>          Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast

知道我如何确保在传递false时也会出错吗?我唯一的想法是添加第二个私有函数"void foo(bool bar)"。然后我确实得到了所需的错误,声明foo(bool-bar)是私有的。但这只适用于从类外调用foo并且它扰乱了我的接口的情况。

首先,关于它为什么接受false而不接受true:文字false将被解释为积分0,文字0将转换为任何类型的空指针。CCD_ 5不能转换为指针类型,因为它转换为积分CCD_。

至于如何解决您的问题:只要您不实现私有重载,您使用额外bool重载的方法对公共和非公共调用方都适用。在这种情况下,公共调用方将得到编译错误,成员调用方将获得链接器错误。

不过,您可能还需要考虑其他事项。

你的函数需要接受空指针吗?如果没有,请将其更改为通过引用接受,问题就会消失。

如果你的函数真的需要接受空指针,那么在这种情况下,我建议相信你的用户会正确调用它,而不是为了防止每一次可能的滥用而扰乱你的界面。

在C++11中,您可以编写:

void foo(bool) = delete; // cannot be use by anybody (class itself included).

由于vs2012不支持= delete

您可以使用SFINAE:尝试此破解

template <typename T>
typename std::enable_if<std::is_same<T, int>::value, void>::type
foo(T* t);

使用旧的C++98方式"私有而不实现":

private:            // Fail to compile from outside
void foo(bool); // No implementation -> fail to link time if internally used.

您可以等待C++17,当Concepts可以在C++11中auto的任何位置使用时,将您的签名写为:

void foo( IsActually<int*>::template test x ) { }

这实际上看起来很糟糕,但到那时他们可能会清理语法。