I am trying to create class that wraps a STL container and adds more
high level features that are specific to my application. And I need to
provide operators that behave in a similar way as begin() and end(),
except that the position returned is different. For instance, here is
one of them.
" iterator InputLayerEnd()
{
ContainerDistance distance = nbNeuronPerLayer_[InputLayer] + 1;
return advance(container_.begin(), distance);
}"
Nothing fancy, I first do some internal computation to figure out
where the real position is, and then use advance to obtain an iterator
pointing to it. My problem is that the compiler does not allow me to
do this, because of a conversion problem. And I do not understand why.
Here is the error
"mlp.hpp:117: could not convert `std::list<_Tp, _Alloc>::begin() [with
_Tp =
MlpNeuron<float>, _Alloc = std::allocator<MlpNeuron<float> >]()' to
`
std::_List_iterator<MlpNeuron<float>, MlpNeuron<float>&,
MlpNeuron<float>*>&
'"
I am using gcc 3.1.1. Here is the declaration of the wrapper class,
which provides definition for the "iterator" and "ContainerDistance"
used in the above function.
"template<template<class> class Container, class T>
class MlpNeuronCollection
{
public:
typedef T element_type;
typedef typename Container<T>::iterator iterator;
typedef typename Container<T>::difference_type ContainerDistance;
typedef long LayerIndex;
enum{InputLayer=1,
OutputLayer=2,
HiddenLayer=3};
protected:
long nbLayer_;
vector<long> nbNeuronPerLayer_;
Container<T> container_;
"
Any ideas of whats wrong? Thanks a lot.
Alexis
[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
> " iterator InputLayerEnd()
> {
> ContainerDistance distance = nbNeuronPerLayer_[InputLayer] + 1;
> return advance(container_.begin(), distance);
> }"
[...]
> Here is the error
>
> "mlp.hpp:117: could not convert `std::list<_Tp, _Alloc>::begin() [with
> _Tp =
> MlpNeuron<float>, _Alloc = std::allocator<MlpNeuron<float> >]()' to
> `
> std::_List_iterator<MlpNeuron<float>, MlpNeuron<float>&,
> MlpNeuron<float>*>&
> '"
You are as close to the solution as reading the documentation of
'advance'. Change your code to something similar to:
iterator InputLayerEnd()
{
ContainerDistance distance = nbNeuronPerLayer_[InputLayer] + 1;
iterator it = container_.begin();
advance(it, distance);
return it;
}
The reason for the error is that, the non-const reference that
'advance' expects cannot be bound to the temporary that 'begin'
returns.
As for the obscurity of the error message: I feel your pain :)
Ali
advance takes a reference and returns a void
iterator i = container_.begin();
advance(i, distance);
return i;
john
> Hi guys,
>
> I am trying to create class that wraps a STL container and adds more
> high level features that are specific to my application. And I need to
> provide operators that behave in a similar way as begin() and end(),
> except that the position returned is different. For instance, here is
> one of them.
>
> " iterator InputLayerEnd()
> {
> ContainerDistance distance = nbNeuronPerLayer_[InputLayer] + 1;
> return advance(container_.begin(), distance);
> }"
>
The correct form of std::advance is:
template <class InputIterator, class Distance>
void advance(InputIterator& i, Distance n);
So what you probably want is:
iterator InputLayerEnd()
{
ContainerDistance distance = nbNeuronPerLayer_[InputLayer] + 1;
iterator iter = container_.begin();
advance( iter, distance );
return iter;
}
> Nothing fancy, I first do some internal computation to figure out
> where the real position is, and then use advance to obtain an iterator
> pointing to it. My problem is that the compiler does not allow me to
> do this, because of a conversion problem. And I do not understand why.
> Here is the error
>
> "mlp.hpp:117: could not convert `std::list<_Tp, _Alloc>::begin() [with
> _Tp =
> MlpNeuron<float>, _Alloc = std::allocator<MlpNeuron<float> >]()' to
> `
> std::_List_iterator<MlpNeuron<float>, MlpNeuron<float>&,
> MlpNeuron<float>*>&
> '"
>
This is odd - I'd take a wild guess that your STL implementation has a
non-standard signature for advance, like:
template <class InputIterator, class Distance>
InputIterator advance(InputIterator& i, Distance n);
Regards,
Andy S.
--
"Light thinks it travels faster than anything but it is wrong. No matter
how fast light travels it finds the darkness has always got there first,
and is waiting for it." -- Terry Pratchett, Reaper Man
> " iterator InputLayerEnd()
> {
> ContainerDistance distance = nbNeuronPerLayer_[InputLayer] + 1;
> return advance(container_.begin(), distance);
> }"
> "mlp.hpp:117: could not convert `std::list<_Tp, _Alloc>::begin() [with
> _Tp =
> MlpNeuron<float>, _Alloc = std::allocator<MlpNeuron<float> >]()' to
> `
> std::_List_iterator<MlpNeuron<float>, MlpNeuron<float>&,
> MlpNeuron<float>*>&
> '"
Advance is a procedure not a function.
void advance (Iter&, dist);
begin() is an rvalue which may not be bound to a non-const reference.
The message is a rather cryptic way of saying that. Since it never
got to call the function, it did not get to complain about the void
return not converting to iterator.
iterator result(container_.begin());
advance(result, distance);
return result;
Jonh
> > " iterator InputLayerEnd()
> > {
> > ContainerDistance distance = nbNeuronPerLayer_[InputLayer] +
1;
> > return advance(container_.begin(), distance);
> > }"
> > "mlp.hpp:117: could not convert `std::list<_Tp, _Alloc>::begin()
[with
> > _Tp =
> > MlpNeuron<float>, _Alloc = std::allocator<MlpNeuron<float> >]()'
to
> > `
> > std::_List_iterator<MlpNeuron<float>, MlpNeuron<float>&,
> > MlpNeuron<float>*>&
> > '"
> Advance is a procedure not a function.
In C++-ese, advance is a function returning void. If we were writing
Pascal, it would be a procedure. And in more general terms, neither C++
nor Pascal have functions, only procedures, because what both languages
call functions actually describes a procedure for calculating a value,
and not the relationship I would expect from a function -- and I know,
this is arguable for a function which consists of a single return
statement, but since functions may consist of many statements, which are
executed in a specified order, I'd say that we are dealing with
procedures.
In this group, however, I believe that the prefered language for such
things is C++-ese. (It is certainly not Pascal-ese.)
--
James Kanze mailto:jka...@caicheuvreux.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
> > Advance is a procedure not a function.
>
> In C++-ese, advance is a function returning void.
I always had a problem with the description "function returning void." I do
not mean I had difficulty understanding the term here. I just think that it
is a historical mistake to call a function that does not return anything "a
function returning void."
Why couldn't we accept the fact that void meant "not returning anything" in
this context? There are already other keywords in the language that mean
different things in different contexts. Why spare void?
In my probably broken C++-ese, void means two things:
void foo(); // function returning nothing
void * p; // pointer that can point to anything
I live happily ever after with this view of the keyword; until of course
someone brings me back to my senses in this thread :o)
I also hear void being referred to as "a special type." Same problem here...
Why do we need to categorize it as a type?
Ali
> jpo...@falcon.lhup.edu (John Potter) wrote in message
> news:<3d9ec0ea...@news.earthlink.net>...
> > Advance is a procedure not a function.
> In C++-ese, advance is a function returning void.
I understand your nit; however, I prefer procedure to nonsense. No
function returns void, there is no void. There is no void function.
Even the original fortran knew the difference between a function and a
subroutine. Procedure just happens to be a better known term today.
Void is a hack to allow procedures in a language which only has
functions which are not functions. ;-)
Your other comments indicate that you only consider fortran arithmetic
statement functions as real functions.
Do you think there was any loss of communication in the statement?
How about a real C++ question? Why did the standard make advance a
useless procedure rather than a useful function? Historical. Any
chance of changing it?
John
I sympathise (though I think the really bad cases are where ctors and
dtors are called functions, which they clearly are not). However the
'returning void' is a grammar fix, which is also why void has to be a
type :-) Pure hackery but that means that for some it is an elegant
solution.
--
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
It's (most probably) an inheritance of the C function (who return an int =
by
default). It's, anyway, that a function returning nothing is void when
ctors/dtors is nothing :)
Christophe Lephay
Hum, if forgot something here, probably a word like "weird"...
> > jpo...@falcon.lhup.edu (John Potter) wrote in message
> > news:<3d9ec0ea...@news.earthlink.net>...
> > > Advance is a procedure not a function.
> > In C++-ese, advance is a function returning void.
> I understand your nit; however, I prefer procedure to nonsense.
If you don't like nonsense, you'd best forget about the C++ standard.
Or any other ISO standard, for that matter; they all give special
meanings to normal, everyday words.
> No function returns void, there is no void. There is no void
> function.
No function modifies global state, either. A function describes a
relationship between the results and the parameters. C++ functions
aren't really functions, even when they return something other than
void.
> Even the original fortran knew the difference between a function and a
> subroutine.
Even the original fortran didn't know what a function was, you mean, and
gave the name function to what is actually a procedure:-).
> Procedure just happens to be a better known term today. Void is a
> hack to allow procedures in a language which only has functions which
> are not functions. ;-)
> Your other comments indicate that you only consider fortran arithmetic
> statement functions as real functions.
That's what a mathematician would say:-).
> Do you think there was any loss of communication in the statement?
Quite frankly, I don't know.
Lately, I've tackled a couple of misnomers in computer science.
Semantics which are really syntax, for example.
Globally, I don't think that there is a real problem in saying that C++
has void functions, or even that grammatical concordance is semantics,
as long as we realize that the context of these meanings is limited, and
that they are NOT the generally accepted meanings outside of the
specific, very limited context.
> How about a real C++ question?
Too easy:-).
> Why did the standard make advance a useless procedure rather than a
> useful function?
Asking why the standard did such and such is the road to insanity.
Advance is a detail -- you can forget it, and still write useful C++.
Try something bigger: why did the standard decide to define template
name lookup in a way no one could understand, and which conflicted with
existing usage? Why did the standard decide that the iostream's should
be templates, then make it impossible to instantiate them for a basic
type, and unrealistically difficult for a user defined type? Why did
the standard define fpos in a way that is mathematically impossible to
implement? Why did the standard define a completely new way of using
locales, but make it impossible for a normal human to use?
Do you want me to go on?
> Historical. Any chance of changing it?
Probably not.
--
James Kanze mailto:jka...@caicheuvreux.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
> > Why did the standard make advance a useless procedure rather than a
> > useful function?
>
> Asking why the standard did such and such is the road to insanity.
> Advance is a detail -- you can forget it, and still write useful C++.
> Try something bigger: why did the standard decide to define template
> name lookup in a way no one could understand, and which conflicted
with
> existing usage? Why did the standard decide that the iostream's
should
> be templates, then make it impossible to instantiate them for a basic
> type, and unrealistically difficult for a user defined type? Why did
> the standard define fpos in a way that is mathematically impossible to
> implement? Why did the standard define a completely new way of using
> locales, but make it impossible for a normal human to use?
>
> Do you want me to go on?
No, but I'd sure like to have answers to those questions, if you have
any.
P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com