如何防止从'0`构造std :: string引起的麻烦?

时间:2011-06-26 13:53:29

标签: c++ string g++ null-pointer

void foo (const std::string &s) {}

int main() {
  foo(0);   //compiles, but invariably causes runtime error
  return 0;
}

编译器(g ++ 4.4)显然将0解释为char* NULL,并通过调用s来构造string::string(const char*, const Allocator &a = Allocator())。这当然没用,因为NULL指针不是指向c字符串的有效指针。当我尝试调用foo(1)时,这种误解不会出现,这有助于产生编译时错误。

当我不小心调用像

这样的函数时,是否有可能在编译时遇到这样的错误或警告
void bar(const std::string &s, int i=1);

bar(0),忘记了string,实际上有i=0的意思?

3 个答案:

答案 0 :(得分:10)

这有点难看,但您可以创建一个在实例化时会产生错误的模板:

template <typename T>
void bar(T const&)
{
    T::youHaveCalledBarWithSomethingThatIsntAStringYouIdiot();
}

void bar(std::string const& s, int i = 1)
{
    // Normal implementation
}

void bar(char const* s, int i = 1)
{
    bar(std::string(s), i);
}

然后使用它:

bar(0); // produces compile time error
bar("Hello, world!"); // fine

答案 1 :(得分:1)

一个有点干净的解决方法......

#include <cassert>

void foo (const std::string &s)
{
    // Your function
}

void foo(const char *s)
{
     assert(s != 0);
     foo(std::string(s));
}

答案 2 :(得分:-2)

实际上静态断言也可以。 考虑一下:

void foo (const std::string &s)
{
    // Your function
}

void foo(const char *s)
{
    #ifdef CPP_OH_X
    static_assert(s == 0, "Cannot pass 0 as an argument to foo!");
    #else
    typedef int[(s != 0) ? 1 : -1] check;
    #endif
    foo(std::string(s));
}

这里的想法是使用static_assert,它是C ++即将推出的功能,已经在各种编译器中实现;主要是支持C ++ 0x的那些。现在,如果您不使用C ++ 0x,则可以使用交替方法,该方法基本上键入一个在失败时具有负值的整数。某些不允许的内容,会在编译时

生成错误