0

I want to inline my two structures. But they have pointer of each other. Like the code below:

A.h

#ifndef A_H
#define A_H

#include "b.h"

struct A
{
    B* b;
    int value;

    A();
    void Inc();
};

#endif // A_H

A.cpp

#include "a.h"

A::A()
{
    b = new B(this);
}

void A::Inc()
{
    b->value++;
}

B.h

#ifndef B_H
#define B_H

struct A;

struct B
{    
    A* a;
    int value;

    B(A* a);
    void Inc();
};

#endif // B_H

B.cpp

#include "b.h"
#include "a.h"

B::B(A *a)
{
    this->a = a;
}

void B::Inc()
{
    a->value++;
}

main.cpp

#include <iostream>
#include <a.h>

using namespace std;

int main()
{
    A a;
    a.value = 0;
    a.b->value = 0;
    a.Inc();
    a.b->Inc();
    cout << a.value << endl;
    cout << a.b->value << endl;
    return 0;
}

I can not use keyword inline anywhere because it gives me the error undefined reference to methods.

Based on here, I can define my methods in header files but that would force me to use #include <a.h> inside the file b.h. But that would give me another error because of duplicate includes.

Now How can I inline both Inc methods?

Community
  • 1
  • 1
Matin Lotfaliee
  • 1,745
  • 2
  • 21
  • 43
  • Just don't try. `inline` is in fact more of a linkage specification nowadays than an actual in-lining hint for the compiler. If you build both source files into one object, I assure you that your compiler is more than smart enough to inline what's needed (and even do optimizations you or I can't think of). – StoryTeller - Unslander Monica Nov 02 '16 at 06:20

2 Answers2

0

It's not possible to inline all member functions of two mutually dependent structs in the body of the struct definition. It's possible to inline all the member functions by defining the functions outside the body of the struct definition and using the inline keyword explicitly. However, if you use two .h files to define the struct/classs, it becomes messy.

Here are some options to implement the member functions.

Option 1

Use only forward declarations in the .h files. Implement all the functions in the .cpp files. None of the member functions are inlined.

Option 2

Use forward declaration of A in B.h but use full definition of B in A. In this case, all member functions of A can be inlined but member functions of B cannot be inlined. They will need to be implemented in a .cpp file.

Option 3

Reverse the roles of A and B from Option 2

Use forward declaration of B in A.h but use full definition of A in B. In this case, all member functions of B can be inlined but member functions of A cannot be inlined. They will need to be implemented in a .cpp file.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 1
    "It's not possible to inline all member functions of two mutually dependent structs." Really? Yes it's not possible to inline them *inside the declaration body* (the place where the method were declared), but nothing stops you to 'inline' them outside, separately, after the full declaration of both structs are fully know. From the perspective of the resulted object files, there's no difference between the two (inline in decl-body or outside it). – Adrian Colomitchi Nov 02 '16 at 07:07
0

a.h and b.h stay the same, a.cpp and b.cpp are merged into ab_inl.hpp containing the methods and constructors with an inline decorator** (or you can let the constructors be in their respective .cpp file) and the main.cpp (or any other file which needs it) includes ab_inl.hpp.


** as the compiler is free to ignore the inline qualifier, I preferred the term "decorator"


Everything below + a.h + b.h compiles just dandy:

File ab_inl.hpp:

#ifndef _AB_INL
#define _AB_INL

#include "a.h"

// included by a.h anyway
// #include "b.h"

inline A::A() : b(0), value(0)
{
    b = new B(this);
}

inline void A::Inc()
{
    b->value++;
}

inline B::B(A *a) : a(0), value(0)
{
    this->a = a;
}

inline void B::Inc()
{
    a->value++;
}

#endif // _AB_INL

File main.cpp

#include "ab_inl.hpp"


int main()
{
    using std::cout;
    using std::endl;

    A a;
    a.value = 0;
    a.b->value = 0;
    a.Inc();
    a.b->Inc();
    cout << a.value << endl;
    cout << a.b->value << endl;
    return 0;
}
Adrian Colomitchi
  • 3,974
  • 1
  • 14
  • 23