Boris
Boris

Reputation: 1457

Strange Template Behaviour

The following code does not compile.:-

#include <vector>

template <typename T>
struct B;

template <typename T>
struct A
{
    B<T> _a;
};

template <typename T>
struct B
{
    A<T> _b;
};


int main()
{
    B<int> c;

    return 0;
}

From the first look the reason seams to be the circular dependency between A and B. However when instead of using type B _b member explicitly, the vector (storing the actual object and not pointer to it) is used. Like this

#include <vector>

template <typename T>
struct B;

template <typename T>
struct A
{
    std::vector<B<T>> _a;
};

template <typename T>
struct B
{
    A<T> _b;
};


int main()
{
    A<int> c;

    return 0;
}

, everything is working fine. And the question is why? If vector needed only size of the B,T> structure so is any part of A in first example because it does not invoke any B's functions.

Upvotes: 0

Views: 54

Answers (2)

Mickael
Mickael

Reputation: 301

In your first example the sizeof(A<int>) and sizeof(B<int>) are defined recursively. Ask yourself: What is the sizeof(A<int>)?

You can't answer because sizeof(A<int>) depends on sizeof(B<int>) and recursively.

In the second example sizeof(A<int>) is sizeof(std::vector<B<int>>) which is constant, indeed std::vector does a heap allocation.

Try to replace std::vector by std::array and you'll have the same issue again. Indeed the size of std::array depends on the size of the elements.

Upvotes: 2

Shoe
Shoe

Reputation: 76240

std::vector's implementation apparently only has pointers and/or references to B<T> as members. Since references and pointers to incomplete types are legal, the program compiles correctly.

Upvotes: 1

Related Questions