Boost logo

Boost :

From: John Maddock (John_Maddock_at_[hidden])
Date: 1999-11-26 07:43:54


Howard -

>I didn't understand this part. Why would inline expansion be prohibited
when iterator is a class? My compiler will inline the following call to
accumulate:

#include <list>
#include <numeric>

int main()
{
        std::list<int> a;
        int sum = std::accumulate(a.begin(), a.end(), 0);
}<

Good point, however I think it depends upon the class type: if the compiler
can determine that the constructor/destructor of the class have no side
effects then the function can be inlined, however if the class does have
side effects then I think I'm right in saying that the copy must be created
(to act as the stack argument) The same arguments apply to return type
optimisations.

> And this seems to work:

template <class iterator>
void
foo(iterator i, typename parameter_traits<iterator>::parameter_type j)
{
        for (; i != j; ++i)
                ;
}<

Nice one, I hadn't thought of that.

There seems to be at least one other use - in container types:

template <class T>
class container
{
public:
        container& push_back(typename parameter_traits<T>::parameter_type
t);
}

This would seem to be OK according to the standard library sequence
container requirements, but not strictly allowable for implementations of
std::list etc, although I don't *think* a conformant program could tell the
difference.

***********

Finally one more suggestion:

parameter_traits<T>::parameter_type effectively evaluates to either "const
T&" or "T", however there is a difference here, if it evaluates to "T" then
we have a modifiable local variable, if to "const T&" then we don't.

So the suggestion is to change the specialisations slightly so that the
local variable is always non-modifiable - this should catch some subtle
bugs in template code which may otherwise be missed in testing, if the
template is only tested with (for example) built in types.

For pointer types:

template< typename T >
struct parameter_traits< T* >
{
    typedef T * decayed_type;
    typedef T * const parameter_type; // pointed to object can be
changed, but not the pointer
};

// for built in types:

template<>
struct parameter_traits<int>
{
    typedef int decayed_type;
    typedef int const parameter_type;
};

//etc

Unfortunately, it seems as if we also need separate specialisations for
cv-qualified built-in types:

template<>
struct parameter_traits<const int>
{
    typedef const int decayed_type;
    typedef const int parameter_type;
};

but this is likely to get very repetitive, I guess we could ignor these as
"uncommon", but maybe a partial specialisation would help here?

- John.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk