Reputation: 12309
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
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
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
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