I am porting a large codebase from Linux/g++ to MacOS/Clang. I hit this compiler error in multiple places in Clang (where g++ builds successfully and does the right thing at run time):
error: initializer-string for char array is too long, array size is 1 but initializer has size X (including the null terminating character)
Note that I'm compiling for c++14.
I've reduced it to a manageable, reproducible case (eliminating all the uninteresting constructors and other methods), where the errors happen in the WTF constructor's assignments:
#include <stddef.h>
struct StringLike
{
const char *str;
size_t len;
StringLike() : str(NULL), len(0) {}
template <size_t LEN_> StringLike(const char (&litAry)[LEN_]) noexcept :
str(litAry), len(LEN_ - 1) {}
StringLike &operator=(const StringLike &rhs)
{str = rhs.str; len = rhs.len; return *this;}
template <size_t LEN_> StringLike &operator=(const char (&strLit)[LEN_])
{str = strLit; len = LEN_ - 1; return *this;}
const char *data() const {return str;}
size_t length() const {return len;}
};
struct WTF
{
StringLike litStrs[3];
WTF()
{
litStrs[0] = {"Is "};
litStrs[1] = {"this "};
litStrs[2] = {"legal?"};
}
};
Yes, I know I could remove the braces from the litStrs[𝒏], and it does work, but I'd like to not change too many lines of code unnecessarily.
I can't figure how Clang is hallucinating a char array of size 1?!? I do see that if I comment out the StringLike templated constructor, I get a similar error from g++; in the working case, g++ code is converting e.g. {"Is "} to a StringLike temporary via that constructor, then passing that to the operator=(const StringLike &rhs) method (note that removing the braces from the WTF constructor's assignments causes the templated operator= method to be invoked directly, instead).
I'm not really sure where to look in the standard to figure out how the WTF brace-enclosed assignments (operator=, not construction) are supposed to be handled, so I'm not sure whether Clang or g++ is right (Clang has a better track record IMO, but I'm stumped what the correct behavior is here).
I used godbolt to verify that all versions of g++ accept this code, and all versions of Clang complain and give up.