Как предотвратить возникновение проблем, возникающих из 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
?
Ответы
Ответ 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, вы можете использовать альтернативный метод, который обычно вводит целое число с отрицательным значением при ошибке. Что-то, что недопустимо и приведет к ошибке в времени компиляции