Re: container traits
Jens Theisen wrote:
Greg Herlihy wrote:
T must be a complete type when std::list<T> is instantiated.
Meaning the following is indeed undefined, as the OP suspected.
>> struct T;
>>
>> typedef std::list<T>::iterator tlist_iterator; // <- UB
Except for the fact that the typedef does not instantiate
std::list<T>::iterator. The type argument for std::list needs to be
complete only at the point of its instantiation, if there is one. (the
latter is a requirement of the Standard Library and not of class
templates in general).
At the point of tlist_iterator's typedef declaration, the compiler has
no idea whether tlist_iterator is ever used subsequently - and
therefore has no idea whether instantiating std::list<T>::iterator is
necessary to complete the program. And unless the instantiation in
question is necessary, the compiler is not allowed to instantiate the
template class implicitly.
Furthermore, the T class can be just as easily implemented without a
typedef:
#include <list>
struct T
{
std::list<T>::iterator mIter;
};
int main()
{
T t; // std::list<T>::iterator instantiated here
...
}
With or without the typedef, the program needs T's type to be complete
no earlier than the first line of main - the point at which a T object
is first declared. And clearly, T is a complete type at that point.
After all, if a class could not declare a member function with its own
type as a parameter, the following declaration would be undefined:
#include <tr1/memory>
struct A
{
std::tr1::shared_ptr<A> next;
};
In other words an class object would not be able to hold a shared
pointer to its own type.
Greg
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]