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

C++ 防止从false到指针的静默强制转换,c++,visual-studio,pointers,C++,Visual Studio,Pointers,我有一个函数 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

我有一个函数

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时也会出错吗?我唯一的想法是添加第二个私有函数“voidfoo(boolbar)”。然后我确实得到了期望的错误,指出foo(boolbar)是私有的。但是这只在从类外部调用foo并且它扰乱了我的接口时起作用。

首先,关于为什么它接受
false
,而不接受
true
:文本false将被解释为整数
0
,而文本
0
将转换为任何类型的空指针<另一方面,code>true无法转换为指针类型,因为它转换为整数
1

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

但是,你也可以考虑另外的事情。

函数是否需要接受空指针?如果不是,则改为通过引用接受,问题就消失了


如果您的函数确实需要接受空指针,那么在这种情况下,我建议您只信任您的用户正确调用它,而不是使您的界面混乱,试图防止任何可能的误用。

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

void foo( IsActually<int*>::template test x ) { }
void foo(实际上是::模板测试x){}
。。。这实际上看起来很糟糕,但到那时他们可能会清理语法。

在C++11中,您可以编写: 由于vs2012不支持
=delete

您可以使用SFINAE尝试此攻击:

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

Clang对此提出了警告…Gcc也给出了警告。但遗憾的是,我们的代码库中只有一小部分是用非Microsoft编译器编译的……您是否尝试提高警告级别?是的,我有4级活动。当设置为C++11或gnu++11模式时,clang现在会抛出一个错误。这是一个很好的解决方案,糟糕,Visual Studio 2012似乎还不支持C++11的这一部分。@fschmitt:我刚刚添加了一个可能适用于vs2012(未经测试)的hack。原因如下:我有foo(int*)和foo(bool)。然后我重构了代码,foo(bool)变成了foo(someEnum)。我依赖于编译器向我展示我必须转换的foo(bool)的所有用法,只有在转换foo(true)10分钟后,我才开始思考为什么我没有得到关于foo(false)的任何错误。
template <typename T>
typename std::enable_if<std::is_same<T, int>::value, void>::type
foo(T* t);
private:            // Fail to compile from outside
    void foo(bool); // No implementation -> fail to link time if internally used.