Static structure initialization with tags in C++
Asked Answered
B

4

5

I've searched stackoverflow for an answer but I cannot get something relevant.

I'm trying to initialize a static structure instance with initial values by specifying their tags, but I get an error at compilation time:

src/version.cpp:10: error: expected primary-expression before ‘.’ token

Here's the code:

// h
typedef struct
{
    int lots_of_ints;
    /* ... lots of other members */
    const char *build_date;
    const char *build_version;
} infos;

And the faulty code:

// C

static const char *version_date = VERSION_DATE;
static const char *version_rev  = VERSION_REVISION;

static const infos s_infos =
{
   .build_date    = version_date, // why is this wrong? it works in C!
   .build_version = version_rev
};

const infos *get_info()
{
    return &s_infos;
}

So the basic idea is to bypass the "other members" initialization and only set the relevant build_date and build_version values. This used to work in C, but I can't figure out why it won't work in C++.

Any ideas?

edit:

I realize this code looks like simple C, and it actually is. The whole project is in C++ so I have to use C++ file extensions to prevent the makefile dependency mess ( %.o: %.cpp )

Braeunig answered 26/4, 2011 at 12:45 Comment(4)
Why is this wrong? it works in C! Mainly because C and C++ are different languages.Halmstad
@David - but with enough in common, and with one derived originally from the other, and with continued sharing of ideas, so that getting stressed about the confusion is unfair. Some parts of C99 have already been imported into C++0x, such as "long long".Varrian
@Steve314: Don't get me wrong, I am not getting stressed on the confusion (I am not getting stressed at all), but there is no confusion in the question: he knows that they are different languages! I find it interesting when people says that because a feature works in C it has to work in C++. Consider this, or void f( int x ) { int array[x]; ...} They are different languages, and while they share a common past, they not always share the future.Halmstad
I get your point, and I totally understand the fact that they are different languages. Thing is, I though something this trivial would be implemented in C++ as well. This is, as far as I know, a very elegant way to setup static structures. On the other hand, I also agree that it is not a very "C++" way of using structures: I should have a constructor.Braeunig
M
7

The feature you are using is a C99 feature and you are using a C++ compiler that doesn't support it. Remember that although C code is generally valid C++ code, C99 code isn't always.

Malliemallin answered 26/4, 2011 at 12:51 Comment(1)
To explain a little more - while C++ originally had a goal of backward compatibility with C, it doesn't necessarily make sense to maintain "sideways" compatibility in the long run. Code written in C but called from C++ is a pain for both - the interface cannot fit the C++ conventions, but it imposes constraints and overheads on C compilers (e.g. exception propagation through C functions) that make some C guys blow smoke out their ears.Varrian
R
5

The following example code defines a struct in what I consider a more C++ way (no need for typedef) and uses a constructor to solve your problem:

#include <iostream>

#define VERSION_DATE "TODAY"
#define VERSION_REVISION "0.0.1a"

struct infos {
    int lots_of_ints;
    /* ... lots of other members */
    const char *build_date;
    const char *build_version;

    infos() : 
        build_date(VERSION_DATE), 
        build_version(VERSION_REVISION) 
    {} 
};

static const infos s_infos;

const infos *get_info()
{
    return &s_infos;
}

int main() {

    std::cout << get_info()->build_date << std::endl;
    std::cout << get_info()->build_version << std::endl;

    return 0;
}
Repay answered 26/4, 2011 at 13:51 Comment(3)
This style of initialisation has a run-time overhead that doesn't exist in the C99 version, at least in principle, though it won't normally be a big overhead and I wouldn't be surprised if some compilers can optimise away the initialisations in some cases, effectively giving the same result as the C99 syntax. It shouldn't need much more than function inlining and compile-time evaluation of constant expressions to handle that in this case.Varrian
@Steve - true, but it has the advantage of being valid C++ so that's a plus (plus) in my book! :)Repay
Although I like this, the runtime overhead is not what I want. I'll stick to the old fashioned "full blown" static definition. Thanks anyway :)Braeunig
A
4

I believe this was added as a feature in C99, but has never been a standard feature in C++.

However, some compilers probably offer it as a non-standard language extension.

Ariminum answered 26/4, 2011 at 12:49 Comment(0)
M
1

I see that this is part of CPP 20 standard now. It is called Designated initializers.

T object = { .des1 = arg1 , .des2 { arg2 } ... };   (3) (since C++20)
T object { .des1 = arg1 , .des2 { arg2 } ... };     (4) (since C++20)
Merilynmeringue answered 20/10, 2022 at 5:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.