c++ - not - nullptr
¿Cómo evito que surjan problemas con std:: string que se construye a partir de `0`? (3)
void foo (const std::string &s) {}
int main() {
foo(0); //compiles, but invariably causes runtime error
return 0;
}
El compilador (g ++ 4.4) aparentemente interpreta 0
como char* NULL
, y construye s
llamando a string::string(const char*, const Allocator &a = Allocator())
. Lo cual, por supuesto, es inútil, porque el puntero NULL
no es un puntero válido para una cadena-c. Esta mala interpretación no surge cuando trato de llamar a foo(1)
, esto produce un error en tiempo de compilación.
¿Existe alguna posibilidad de obtener un error o advertencia de este tipo en tiempo de compilación cuando accidentalmente llamo una función como
void bar(const std::string &s, int i=1);
con la bar(0)
, olvidarse de la string
y, en realidad, significa tener i=0
?
En realidad, las afirmaciones estáticas también funcionan. considera esto:
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));
}
La idea aquí es usar static_assert, que es una característica próxima en C ++ y ya está implementada en varios compiladores; primordialmente los que soportan C ++ 0x. Ahora, si no está utilizando C ++ 0x, puede usar el método alternativo, que básicamente tipifica un entero con un valor negativo en caso de falla. Algo que no está permitido y producirá un error en tiempo de compilación
Esto es un poco feo, pero podría crear una plantilla que generará un error cuando se ejemplifique:
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);
}
Entonces usándolo:
bar(0); // produces compile time error
bar("Hello, world!"); // fine
Una solución algo limpia ...
#include <cassert>
void foo (const std::string &s)
{
// Your function
}
void foo(const char *s)
{
assert(s != 0);
foo(std::string(s));
}