41

I have code in C that compiles and works correctly and I would like to use similar code in C++:

static const char* aTable[12] = {
    [4]="seems",
    [6]=" it  ",
[8]="works",};

int main(){
    printf("%s%s%s", aTable[4],aTable[6],aTable[8]); 
    return 0;
}

Now if I put it in a .c file and compiles with gcc it works. But, if I put it in a .cpp file and compile it with g++, I get the following errors:

test_cpp.cpp:5:3: error: expected identifier before numeric constant
test_cpp.cpp:5:4: error: type '<lambda>' with no linkage used to declare function 'void<lambda>::operator()() const' with linkage [-fpermissive] 
test_cpp.cpp: In lambda function: test_cpp.cpp:5:5: error: expected '{' before '=' token 
test_cpp.cpp: At global scope: test_cpp.cpp:5:5: warning: lambda expressions only available with
    -std=c++0x or -std=gnu++0x [enabled by default] 
test_cpp.cpp:5:6: error: no match for 'operator=' in '{} = "seems"' test_cpp.cpp:5:6: note: candidate is: test_cpp.cpp:5:4: note: <lambda()>&<lambda()>::operator=(const<lambda()>&) 
test_cpp.cpp:5:4: note:   no known conversion for argument 1 from 'const char [6]' to 'const<lambda()>&' 
test_cpp.cpp:6:3: error: expected identifier before numeric constant
test_cpp.cpp:6:4: error: type '<lambda>' with no linkage used to declare function 'void<lambda>::operator()() const' with linkage [-fpermissive]

Is there a way to express that I am not declaring a lambda function, just trying to fill a table?

I would like to keep the following part :

[4]="seems",
[6]=" it  ",
[8]="works",

because it comes from an autogenerated file...

Fantastic Mr Fox
  • 32,495
  • 27
  • 95
  • 175
Aname
  • 515
  • 4
  • 16

5 Answers5

28

You can mix C and C++ code easily.

You should keep the C code to be compiled with C compiler (gcc), rest of the code can be C++ and be compiled with C++ compiler (g++). then link all object (.o) files together.

like this:

file name: a.c

const char* aTable[12] = {
    [4]="seems",
    [6]=" it  ",
[8]="works",};

file name: b.cpp

#include <cstdio>
extern "C" const char* aTable[12];   
int main(){
    printf("%s%s%s", aTable[4],aTable[6],aTable[8]); 
    return 0;
}

Now compile:

gcc -c a.c -o a.o
g++ -c b.cpp -o b.o
g++ b.o a.o -o all.out

Now run the executable (all.out) and you'll see that everything will work.

Just note that for functions you'll need to add extern "C" before the declaration in the cpp file.

SHR
  • 7,940
  • 9
  • 38
  • 57
16

There's no way to do this. C++ never adopted this particular C syntax.

In your case, since the table is auto-generated, I would just put it in a C file. As long as it's not marked static, it can be accessed from C++ code without problems.

13

[4]= is a designated initializer, one of the C features not supported by C++.

Here is a list that tries to list which C99 features that are supported by C++17. Scroll down to the bottom to see which ones that are not supported.

It is important to realize that C++ is by no means a superset of C.

Lundin
  • 195,001
  • 40
  • 254
  • 396
5

Designated initialisers not being supported by C++ already mentioned – if you insist on C++, you could write a wrapper class with a constructor instead:

class Table
{
    std::array<char const*, 12> data;
public:
    Table()
    {
        data[4] = "seems";
        data[6] = " it  ";
        data[8] = "works";
    }
    char const* operator[](unsigned int index) const
    {
        return data[index];
    }
} aTable;

Did not test the code, so if you find a bug, feel free to fix it yourself...

Aconcagua
  • 24,880
  • 4
  • 34
  • 59
2

As said above, this type of initialization is not supported in C++, but you could use lambda function to initialize static array<const char*, 12> like this:

#include <array>
#include <cstdio>

static const std::array<const char*, 6> aTable = []() {
    std::array<const char*, 6> table;
    table[0] = "Hello";
    table[3] = ", ";
    table[5] = "world!";
    return std::move(table);
}();

int main() {
    printf("%s%s%s\n", aTable[0], aTable[3], aTable[5]);
    return 0;
}

Demo on coliru

Notable, that compiler will do RVO here, and the initialization will be performed in-place. This is assembly generated by g++-5.4.0:

<_GLOBAL__sub_I_main>:
movq   $0x40064c,0x200bc5(%rip)        # 601060 <_ZL6aTable>
movq   $0x400652,0x200bd2(%rip)        # 601078 <_ZL6aTable+0x18>
movq   $0x400655,0x200bd7(%rip)        # 601088 <_ZL6aTable+0x28>
retq   
ivaigult
  • 6,198
  • 5
  • 38
  • 66