2

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?

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
ABu
  • 10,423
  • 6
  • 52
  • 103
  • Not related to the central point of your question but clang gives me a warning because of: http://stackoverflow.com/questions/4866425/mixing-class-and-struct – Flexo Feb 11 '13 at 20:37

3 Answers3

4

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.

Casey
  • 41,449
  • 7
  • 95
  • 125
2

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.

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • How much code is instantiated when I instance a class, but I don't use any member? – ABu Feb 11 '13 at 20:46
  • If I substitute `C::value` by `false`, I get a compile error always (even commenting the declaration `test t;`). If `testing` is not instantiated, why does compilation fail? – ABu Feb 11 '13 at 20:50
  • @Peregring-lk: If you don't use any member, no *code* will be instantiated. Also, if you replace `C::value` by `false`, the compiler will detect that your template has no possible valid instantiation (the condition `false` does not depend on any template parameter), so it can directly emit a compilation error before even instantiating the function. – Andy Prowl Feb 11 '13 at 20:55
1

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.

Damon
  • 67,688
  • 20
  • 135
  • 185
  • It wouldn't fail actually, because at the point of instantiation (when you call `testing()` in `main()`) the definition of `A` is visible. – Andy Prowl Feb 11 '13 at 20:42