19
void foo (const std::string &s) {} int main() { foo(0); //compiles, but invariably causes runtime error return 0; } 

The compiler (g++ 4.4) apparently interprets 0 as char* NULL, and constructs s by calling string::string(const char*, const Allocator &a = Allocator()). Which is of course useless, because the NULL pointer is not a valid pointer to a c-string. This misinterpretation does not arise when I try to call foo(1), this helpfully produces a compile-time error.

Is there any possibility to get such an error or warning at compile-time when I accidentally call a function like

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

with bar(0), forgetting about the string, and actually meaning to have i=0?

4
  • 3
    Not really without some help from the compiler. Some implementations have added a private basic_string(int) to catch this case. If not, I guess you are out of luck. Commented Jun 26, 2011 at 14:01
  • I'm surprised that this pass gcc, it's known for its ugly errors/warnings, but I would have expected something here. Did you crank up the warning level ? Commented Jun 26, 2011 at 16:00
  • @Matthieu I could not find any options that give me a warning, but I'm not really into gcc warning options. -W -Wall -Wpointer-arith -Wcast-qual does not do the trick, at any rate. Commented Jun 27, 2011 at 9:03
  • I tested with clang (using gcc headers), and it didn't trigger any warning either :( Commented Jun 27, 2011 at 9:20

3 Answers 3

10

This is kind of ugly, but you could create a template that will produce an error when instantiated:

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); } 

Then using it:

bar(0); // produces compile time error bar("Hello, world!"); // fine 
Sign up to request clarification or add additional context in comments.

1 Comment

+1 even though this approach fails if T actually has a public static method called youHaveCalledBarWithSomethingThatIsntAStringYouIdiot and takes no arguments ;)
1

One somewhat clean workaround...

#include <cassert> void foo (const std::string &s) { // Your function } void foo(const char *s) { assert(s != 0); foo(std::string(s)); } 

2 Comments

Except this is run-time, not compile-time.
@robert I know, it's just one possible solution.
-2

Actually static asserts would work too. consider this:

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)); } 

The idea here is to use static_assert which is a upcoming feature in C++ and is already implemented in various compilers; primarly the ones that support C++0x. Now if you're not using C++0x you can use the alternitive method, which basicly typedefs an integer with a negitive value on failure. Something which is not allowed and will produce an error at compile time

3 Comments

This certainly looks cleaner than the template hack, but it does not seem to work: implctstringparam.cpp: In function ‘void foo(const char*)’: implctstringparam.cpp:9: error: ‘s’ cannot appear in a constant-expression
The const std::string& s would most likely need to be static inorder for static assertion to work.
The value of s is only known at runtime, when the function is called: you cannot use it in a static_assert, which is evaluated at compile-time. A static_assert can only evaluate constant expressions.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.