c++visual-studioclang++

Why compilers treat differently parenthesized type followed by an initializer list in C++?


Why the same code below compiles fine with CLang and doesn't compile with MSVC?

#include <iostream>

const char * NumberToText(int val)
{
    return (const char *[]) {
        "Zero",
        "One",
        "Two", 
    }[val];
}

int main()
{
    std::cout << NumberToText(2);
}

Here is the demo.

And MSVC gives the error:

(5): error C4576: a parenthesized type followed by an initializer list is a non-standard explicit type conversion syntax

At the same time CLang compiles and executes this just fine.

In the Error C4576 in VS2015 enterprise I see some ideas that this is because this is C language feature and this is ill-formed in C++, but why CLang compiles this, then?

Can I keep the array anonymous and still get the same result in MSVC C++?


Solution

  • The syntax (T){E1, E2, ...}, where T is a type and E* are expressions, is not valid standard C++ syntax.

    It is valid C though, where it is a so-called compound literal. Some compilers allow compound literals in C++ code when not compiling in a strict standard-compliance mode (e.g. -pedantic-errors), but it is not obvious how these compound literals behave in a C++ context.

    In particular, in GCC (and probably Clang as well), compound literals have different semantics in C++ code than in C code. Their lifetime and value category are different. See https://gcc.gnu.org/onlinedocs/gcc/Compound-Literals.html.

    So, I suggest not using them, even if you only compile for compilers supporting them.

    Your example can be easily rewritten in standard-conforming C++:

    return std::array{
        "Zero",
        "One",
        "Two", 
    }[val];
    

    or pre-C++17:

    return std::array<const char*, 3>{
        "Zero",
        "One",
        "Two", 
    }[val];