String literals are array objects:
typeid("hello").name() // char [6]
This seems convenient because the size of the string literal (=array) is known at compile time. So why is there no constructor to std::string that takes a reference to an array?
// this would be great
template <int N>
std::string(const char (& array)[N]);
Instead there are constructors that take const char * s, const char * s, size_t n or two InputIterators (eg. const char * begin, const char * end). All of these have drawbacks; the array is implicitly converted to a pointer and the size information is lost, so various methods are used to get it back. Working, but increasingly crazy examples:
// std::string(const char * s) version:
std::string s1("hello"); // calls std::strlen(s) internally
// std::string(const char * s, size_t n) version:
std::string s2("hello", 5); // programmer does std::strlen(s) mentally
std::string s3("hello", sizeof("hello")); // have to repeat string literal
// macro helper to avoid repeating string literal (ugly and dangerous)
#define STRLIT(x) std::string(x, sizeof(x)); // could be a function I guess
std::string s4 = STRLIT("hello"); // not much improvement (and macros are evil)
// std::string(InputIterator begin, InputIterator end) version:
char tmp[] = "hello"; // copy array
std::string s5(&tmp[0], &tmp[sizeof(tmp)]); // so you can reference it twice
// or trust the compiler to return the same address for both literals
std::string s6(&"hello"[0], &"hello"[sizeof("hello")]); // totally crazy
The key question when considering whether there should be a constructor taking a
char const (&)[N](for some statically determinedN) is what the content of the resultingstd::stringshould be. It might be obvious to some what it should be but I don’t think it is. Consider thisstd::string("abc\0def"):If you use
you get the third option. It seems, this is the only sane alternative…