Как предотвратить проблемы, возникающие из-за того, что std :: string создается из `0`? - PullRequest
19 голосов
/ 26 июня 2011
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 ]

10 голосов
/ 26 июня 2011

Это немного уродливо, но вы можете создать шаблон, который будет выдавать ошибку при создании экземпляра:

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 голос
/ 26 июня 2011

Один довольно чистый обходной путь ...

#include <cassert>

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

void foo(const char *s)
{
     assert(s != 0);
     foo(std::string(s));
}
0 голосов
/ 27 июня 2011

На самом деле статические утверждения тоже будут работать. Учтите это:

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, вы можете использовать альтернативный метод, который в основном typedef определяет целое число с отрицательным значением при ошибке. То, что не разрешено и выдает ошибку при время компиляции

...