Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Error in function not detected when not called

96 views
Skip to first unread message

kiran

unread,
Aug 29, 2012, 6:44:31 PM8/29/12
to

Hi have a following class:
====================================
template <class T>
class List
{
protected:
ListNode<T> *first;

public:
...
int remove(T& t);
...
};

//The member function is defined as:
template <class T>
int List<T>::remove(T& t)
{
if(isEmpty()) return 0;
ListNode<T> q = first;
first = first->next;
t = q->data;
delete q;
return 1;
}
====================================

The member function incorrectly assigns a ListNode object q to the
ListNode pointer first. However when I compile it (using g++ on
redhat) I dont get any error if I don't call the function. However, if
I do call the function somewhere in the program I get the error.

I have tried to compile using various optimization levels (O0, O1, O2,
O3) and yet compiler doesn't give error. Anyone knows why?

Many thanks,
Kiran


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Richard Damon

unread,
Aug 30, 2012, 5:49:42 AM8/30/12
to
{ Please limit your quoting to the minimum needed to establish context
- mod }
Since remove() is a template, the compiler is not supposed to check
for this type of error because it is quite possible that for the type
of T that the template is substantiated on has a specialization that
is different from the "default" that has been listed, and thus perhaps
the function is actually legal.

Daniel Krügler

unread,
Aug 30, 2012, 5:43:10 AM8/30/12
to
This is how (unconstrained) templates are supposed to work. Types and
values that depend on at least one template parameter are /dependent/
and the compiler cannot (usually) safely reject above assignment
without having a concrete instantiation. To give you a better picture
of the problem, lets assume your definition of template ListNode looks
like this:

template<class T>
struct ListNode {
};

If that would be the only possible way to instantiate a ListNode
instance, the compiler could easily find out that above line

ListNode<T> q = first;

could never be well-formed, because there is no conversion from
ListNode<T>* to ListNode<T>.

The problem is, that the compiler cannot safely assume that, because
there *could* be any specialization (partial or not partial), that
*would* allow a conversion from a pointer. E.g. someone could write:

template<>
struct ListNode<int> {
ListNode(ListNode*);
};

This means, unless the compiler has a concrete specialization and can
look at all possible conversion paths, it cannot really reject the
code as ill-formed, because it is *potentially well-formed*.

Only expressions that are not dependent or some very rare combinations
that can never be valid in any case, can be rejected without having a
concrete instance available.

HTH & Greetings from Bremen,

Daniel Krügler

Richard

unread,
Aug 30, 2012, 5:46:01 AM8/30/12
to

[Please do not mail me a copy of your followup]

kiran <kiran.t...@googlemail.com> spake the secret code
<231e41e1-d5b2-4e5b...@googlegroups.com> thusly:

>I have tried to compile using various optimization levels (O0, O1, O2,
>O3) and yet compiler doesn't give error. Anyone knows why?

Because you have no unit tests for your class.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Ulrich Eckhardt

unread,
Aug 30, 2012, 5:52:25 AM8/30/12
to

Am 30.08.2012 00:44, schrieb kiran:
> The [template] member function incorrectly assigns a ListNode object
> q to the ListNode pointer first. However when I compile it (using
> g++ on redhat) I dont get any error if I don't call the
> function. However, if I do call the function somewhere in the
> program I get the error.

The key point is that templates are only instantiated when used, so
the incorrect assignment is not detected until the function is
actually created for some type T. Without that, the function can be
parsed correctly (no mismatched brackets etc). The FAQ also deals a
bit with this issue, only that it addresses the problem with linker
errors that come from non-instatiation of templates.

Apropos "int remove(T& t);": My questions there is what the returned
number is and in what way the supplied T is modified. From the
implementation, I see that the T reference is a pure output parameter
of the element that was removed from the sequence. This operation is
typically called "pop", like for a queue (FIFO) or stack (LIFO).
Further, the returned integer is 0 or 1, which is better modelled
using a bool or avoided altogether using an exception when there is no
element.

Good luck!

Uli

bartek szurgot

unread,
Aug 30, 2012, 5:57:28 AM8/30/12
to

{ Please limit your quoting to the minimum needed to establish context
- mod }

methods of template classes are instantiated upon usage. when it is
not called, only basic syntax is checked. it is so because w/o exact
type compiler is not able to determine if given code is correct.
imagine that ListNode<T> could have specialization for some type, that
would have required c-tor defined - could would be correct then.

this is actually a nice feature. common example is std::map<>, that
has operator[] defined. but you need to have a default c-tor for the
element, in order to be able to use it. if element does not have
default c-tor, you can always call insert() and as long as you won't
try using operator[], everything is fine.

--
pozdrawiam serdecznie / best regards,
bartek szurgot
/* http://www.baszerr.eu */
0 new messages