ABu
ABu

Reputation: 12309

Must this code works?

I have the next sample code that compiles with gcc (4.7.2 using -std=c++11):

template<class C>
struct template_test
{
    C testing() const
    {
        return C();
    }
};

class A;

struct test : public template_test<A> // (1)
{};

struct A
{};

int main()
{
    test t;
}

At point (1) the function template_test<A>::testing() is instantiated, and use a function of A, specifically its default constructor. Therefore, test contains this instantiated function as a function member. However, at this point A is an incomplete type, and C++ prohibits you to use members of a incomplete type.

Is this a positive gcc's error or is there another explanation?

Upvotes: 2

Views: 106

Answers (3)

Casey
Casey

Reputation: 42594

Not only is template_test::testing() not instantiated at (1), it's never instantiated in this program. Template members are only instantiated on use, and testing() isn't used. To make this more clear, change the code slightly to:

template<class C>
struct template_test
{
    C testing() const
    {
        return C::foo();
    }
};

class A;

struct test : public template_test<A> // (1)
{};

struct A
{};

int main()
{
    test t;
}

which also compiles and runs fine.

Upvotes: 4

Damon
Damon

Reputation: 70206

You are instantiating a template with an incomplete type, this is OK.

The member function testing returns an instance of an incomplete type, which is not OK (but whether or not that's OK only comes into discussion when it's instantiated). However, you never call that function, so it is never instantiated, and thus there is no error. Instantiating the structure alone (and calling its constructor/destructor) is harmless.

Therefore, GCC is correct in letting you compile that. It would fail the moment you try to call testing.

Upvotes: 1

Andy Prowl
Andy Prowl

Reputation: 126552

That's all right. The testing() member function won't get instantiated until you will actually invoke it. To see this, try rewriting it as follows:

C testing() const
{
    static_assert(C::value, "Error!");
    return C();
}

You'll see that no compilation error is issued until you try to invoke the function, but the static assert will be triggered when you add t.testing() to your main() function.

In other words, your premise that "At point (1) the function template_test<A>::testing() is instantiated" is incorrect.

Upvotes: 2

Related Questions