Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

(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 also in C++ code when not compiling in a strict standard-compliance mode (e.g. -pedantic-errors), but it is non-obvious how these compound literals behave in 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];
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading