Question

template <typename T>
void list<T>::copyAll(const list &l)
{
    if(l.isEmpty()) //if the list-to-copy is empty, we're done
    {
        first = last = NULL;
    }
    else
    {
        node *toFollow = l->yhjfrtydfg;
        node *whatever = l.asfqwejfq3fqh23f8hq23r1h23017823r087q1hef;

        while(toFollow != NULL)
        {
            T *newO = new T(*(toFollow->o));
            T here = *newO;
            insertBack(&here);
            toFollow = toFollow->next;
        }
    }
}

This program compiles (with the rest of the program), even though the two lines node *toFollow = l->yhjfrtydfg; and node *whatever = l.asfqwejfq3fqh23f8hq23r1h23017823r087q1hef; are clearly crazy input. It's strange because any other error is caught. Any help?

Was it helpful?

Solution

"Dependent names" (names used in templates whose meaning depends on the template parameters) are only resolved when the template is instantiated, not when it's defined. If you don't instantiate the template, then it can contain whatever crazy names you like, as long as it's syntactically correct.

Your program would fail to compile if it were instantiated:

list<int> l;
l.copyAll(l); // ERROR

OTHER TIPS

Names that depend on a template parameter are only resolved once the template is instantiated. Only non-dependent names are resolved in any case.

C++ coined this "two phase lookup", where phase 1 is when it is first parsed, and phase 2 is instantiation time.

E.g.:

template <typename T>
void frob() {
    foo = 5; // non-dependent, name must exist at this point
    T bar;
    bar.frobnicate = 7; // dependent, name is looked up upon instantiation

    bar->is->a.funny(T::hing); // dependent, likewise looked up later
}

The nonexistent members are the least of your worries- the compiler does not complain because some T might indeed have those members. The fundamental source of your confusion is that the compiler just sees an indentifier like any other- it is only your perception that nobody would use this and clearly no type T has them that makes the input "crazy". It is not crazy at all. It is just an identifier.

        T newO = new T(*(toFollow->o));
        insertBack(&newO);
        toFollow = toFollow->next;

Is completely and utterly broken. First, you dynamically allocate a T and then try to construct a stack-allocated T from it? No T behaves this way. Then you keep a pointer to a stack-allocated object.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top