Подтвердить что ты не робот

Как предотвратить возникновение проблем, возникающих из std::string, построенных из `0`?

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?

4b9b3361

Ответ 1

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

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

Ответ 2

Одно из нескольких способов обхода...

#include <cassert>

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

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

Ответ 3

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

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, которая является предстоящей функцией на С++ и уже реализована в различных компиляторах; в первую очередь те, которые поддерживают С++ 0x. Теперь, если вы не используете С++ 0x, вы можете использовать альтернативный метод, который обычно вводит целое число с отрицательным значением при ошибке. Что-то, что недопустимо и приведет к ошибке в времени компиляции