2011-06-26 28 views
19
void foo (const std::string &s) {} 

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

编译器(克++ 4.4)显然解释0char* NULL,并通过调用string::string(const char*, const Allocator &a = Allocator())构建s。这当然是无用的,因为NULL指针不是指向c字符串的有效指针。当我尝试呼叫foo(1)时,这种错误解释不会产生,这有助于产生编译时错误。如何避免由'0'构造std :: string引起的麻烦?

是否有可能得到这样的错误或警告在编译的时候,我不小心调用诸如

void bar(const std::string &s, int i=1); 

功能与bar(0),忘掉了string,实际上意味着有i=0

+3

不是没有编译器的帮助。一些实现已经添加了一个私有'basic_string(int)'来捕获这种情况。如果不是的话,我想你的运气不好。 –

+0

我很惊讶,这通过海湾合作委员会,它的丑陋的错误/警告,但我会在这里预期的东西。你有没有提高警告水平? –

+0

@Matthieu我找不到任何可以给我警告的选项,但我并没有真正进入gcc警告选项。无论如何,-W-Wall -Wpointer-arith -Wcast-qual'并没有诀窍。 – leftaroundabout

回答

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 
+5

+1,即使此方法失败,如果'T'实际上有一个名为'youHaveCalledBarWithSomethingThatIsntAStringYouIdiot'的公共静态方法并且不带任何参数;) –

1

一个稍微干净的解决办法...

#include <cassert> 

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

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

除了这是运行时,不是编译时。 – robert

+0

@robert我知道,这只是一个可能的解决方案。 –

-1

实际上,静态断言也会起作用。 考虑这个问题:

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,则可以使用交替方法,该方法基本上会在失败时键入一个具有负值的整数。有些东西是不允许的,会在编译时产生错误

+0

这肯定看起来比模板黑客更清洁,但它似乎不工作:'implctstringparam.cpp:在函数'void foo(const char *)': implctstringparam.cpp:9:错误:'s'不能出现在一个常量表达式' – leftaroundabout

+0

const std :: string&s很可能需要静态inorder才能使静态断言生效。 – graphitemaster

+1

只有在运行时才知道's'的值,当函数被调用时:你不能在'static_assert'中使用它,这是在编译时计算的。一个'static_assert'只能计算常量表达式。 –