0

I already highly suspect it's doable and not risky at all but I still want to know for sure, so here's my thing...

I have a C++ code that use quite big structs (15-30 fields) as containers, as arguments for the constructor of a class. The thing with those structs is that I need to declare them using the C99 syntax (incompatible with C++ ffs):

FooBar fb = { .foo = 12, .bar = 3.4 };

Because it's unthinkable for me to have a constructor, since some fields can be safely skipped while initializing those structs, while others are not, etc. (they are only and exclusively initialized by "user supplied" data, user is me in the occurence), a bit like if they described a configuration.

Anyways, point made, I'm down to using one .h header that declares the struct using plain C syntax, and one .c file containing the structs I initialize, and THEN I make them accessible in my .cpp files using extern "C". It works well... except I would find very handy to be able to have methods for those structs.

So my question is, is it possible to a declare struct like so

#ifdef __cplusplus
    // C++ compatible declarations with methods
    struct foobar {
        int foo;
        float bar;

        int method1();
        int method2();
        void method3();
        [etc.]
    };
#else
    /* C compatible declarations, no methods */
    struct foobar {
        int foo;
        float bar;
    };
#endif

This way I could use in C++ some methods bound to the structs (its more elegant, OOP oriented), and I could safely initialize them in my C code using C99's designated initializers.

What I fear is some potentially unknown-by-me issues that could end up making the struct offets different in the C code than in the C++ code. Do those issues exist, or not?

Thanks

10
  • Not sure I understand this correctly: Do you need the C99 designated initializers feature for convenience or because you need to initialize those objects within (existing) C code? Commented Sep 17, 2015 at 23:57
  • No I declare a set of structs in a C file, using C99's designated initializers, and I then use those structs that are into the C file in my C++ code (using extern "C" struct_name blabla to make them accessible in the CPP code) Commented Sep 17, 2015 at 23:59
  • Yes but the "Because it's unthinkable for me to have a constructor [...]" paragraph to me sounds a bit like you're initializing the objects in a C file because C(99) has the designated initializer feature. Is this the case, or are there other reasons why you do that? Commented Sep 18, 2015 at 0:00
  • Erm I actually didnt answer your question. Yes I need C99 designated initializers for convenience. Making a constructor with 30 arguments when in some cases I only need to initialize 3-4 fields would not be pretty at all. The constructor model here to "replace" the designated initializers doesnt fit at all in this case (too many params), hence why I do the initialization work in a C99 file. Commented Sep 18, 2015 at 0:00
  • 1
    I have a C++ code that use **quite big structs (15-30 fields)** << this could be the real issue. As you care about more elegant, OOP oriented things, consider scenario where you implicitly solve the problem in the question by properly designing your objects (instead of inventing hacks). SRP is violated here. Remove The God Object, put smaller, maintainable objects instead. Commented Sep 18, 2015 at 0:20

1 Answer 1

1

In C++11, if your struct is standard-layout, then it has the same layout as an equivalent C struct. The rules for what constitutes a standard-layout structure are as follows:

A standard-layout class is a class that:

— has no non-static data members of type non-standard-layout class (or array of such types) or reference,

— has no virtual functions (10.3) and no virtual base classes (10.1),

— has the same access control (Clause 11) for all non-static data members,

— has no non-standard-layout base classes,

— either has no non-static data members in the most derived class and at most one base class with non-static data members, or has no base classes with non-static data members, and

— has no base classes of the same type as the first non-static data member.

Since your structure only has a few public data members, and a few non-virtual methods, your structure is standard-layout. You could express it with less duplication as

struct foobar {
    int foo;
    float bar;
#ifdef __cplusplus
    int method1();
    int method2();
    void method3();
#endif
};

In prior versions of C++, your type would have to be a plain-old-data (POD) type, and there are some more restrictions. However, your struct would still be POD (no virtual functions, no constructors or destructors, no base class), so it would still be layout-compatible with C.

Sign up to request clarification or add additional context in comments.

4 Comments

Standard-layout is supposed to make the layout compatible with C, however, the details are not strictly specified by the C++ Standard and left for the implementation. I wouldn't be surprised if the OP's approach caused issues with ODR or strict aliasing.
Could I ask you, I understand the fact it doesnt need to have any virtual stuff inside the class, as it would create a vtable at the beginning of the struct and thus change the offets. but why no constructor (plain curiosity, not that I need one in my specific need)? Does a constructor (that isnt virtual) modifies the internal struct layout a bit like virtual members do?
@Yannick: The old POD definition is more restrictive than the new standard-layout definition. POD classes also have to be statically initializable, i.e. they have to be initializable without any special code (think being able to resize a vector of objects without calling any constructors).
But to answer your direct question: constructors shouldn't cause any layout changes, although this is (of course) up to the discretion of the C++ compiler implementor.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.