Boost logo

Boost :

From: emilyw_at_[hidden]
Date: 2001-11-27 18:49:13


> > People who write _normal_ functions manage to cope somehow
> > without naming their return value :)
>
> Yeah, I wondered how I do it too :). IMO "normal" functions can be
> classified into the same two categories as well: ones which return value's
> type is obvious from the name of the function (i.e. which are in the same
> category as add_const<>; "person.name()" is one example, although may be a
> controversial one :), and the ones for which you infer the information about
> their return value's type _mainly_ from the function's signature or its
> usage context (or from reading the docs :); for example, if it was possible
> to write:
>
> std::pair<my_iterator, bool> res(map.insert(777));
>
> as
>
> auto typename T res(map.insert(777));
>
> when one would have no chances to guess what type "res" is, without looking
> at std::map<>::insert signature, or reading the docs (supposing that it's
> the first time she came across this function, of course :).

.. and one would promptly have to look at the docs in any case, to work out what on earth "res" is _for_! It seems that if the return type is non-obvious, the purpose of the return value is also likely be non-obvious.

> So, the issue is pretty much the same in the "run-time world" as well, it's
> only shaded a little bit by the language strong static type system that
> forces you to write clues about function return type all over the place :).
> Hmm, just realized that I haven't thought about dynamic-typed languages :).

I realised that I have to go and learn several other languages before I have a hope of understanding C++ :)

> Hmm.. may be the ability to write both 'begin<seq>::iterator' as well as
> 'begin<seq>::type' is indeed a misfeature, and we should stick to simple and
> consistent "::type" everywhere.. what do you think?

Yep, definitely.

> > Also useful would be a convention for denoting the return
> > type of a runtime function, where that type depends on the
> > template parameters of the function, like this
> >
> > struct X{
> > template<class T> struct get_return_type{
> > typedef typename long_calculation_with_T<T>::type type;
> > };
> > template<typename T>
> > typename get_return_type<T>::type
> > operator()( /* whatever */ ){
> > /* runtime stuff */
> > }
> > };
>
> Yes, IMO handling both runtime and compile-time computations
> simultaneously/in the same place makes a perfect sense, and often it's the
> only way to do things effectively. In fact, chances are that I would write
> the above as
>
> template<typename T>
> struct X {
> typedef typename calculation_with_T<T>::type type;
> type operator()( /* whatever */ ){
> /* runtime stuff */
> }
> };

But that forces you to pass X around as a template template parameter until you know T, and I don't like template template parameters ;) Particularly it means that in order to access any parts of X that don't depend on T, you have to provide a dummy T type.

Having T as template parameter to the operator() is also nice if you are taking a T as a parameter, so you can infer T and save the user having to know what it is at all. Makes their code look a lot nicer if T actually turns out to be

typename big_long_name<X, Y>::type

:)

Unfortunately that still leaves the requirement for a convention about what to call my get_return_type function.

> > Strange compared to which other compile-time iterator
> > equality check? ;) I don't see any other way to do that:
> > your way is exactly the same way as I came up with.
>
> Well, at least yours is hided inside of the iterator type itself :).

Yet another thing that requires an agreement on conventions: compile time equality comparison. We can't call it operator==...

> > The thing where the function object itself can change type is
> > actually a neater way to do what I've been trying to do all
> > along. I had the function object calling a Thingy that the
> > user could specialise.
>
> I like your names :).

Well, each function object has a differently-named Thingy, and I just wanted a word that would encompass all of them... Actually the Germans have a word Dingsbums that says the same thing but sounds much better.

> I am afraid I don't have enough information to analyze
> how different our _applications_ of the tuple algorithms are (but from what
> you've said, it seems that they are be different), but my main motivation to
> give a function object a possibility to change its type was to allow one to
> accumulate internal state on each step of iteration; I guess I need to see
> some examples to be able to grasp a need for specialization here :).

I am still not convinced that my application is useful to real people, rather than just something fun to occupy too much of my time :) Nevertheless, if you have a class whose members are stored in a tuple, you can put something like

my_class::my_class(const my_class& other){
  std::auto_ptr<varlist_type> pVars(new varlist_type(*other.vars));
  transform(other.vars->begin(), other.vars->end(), pVars->begin(), complicated_copy_function());
  vars = pVars.release();
};

and have this code deep copy pointers in my_class. But this is of limited utility unless there is some way of specifying that objects of type X should be copied by means of a Clone function, and that the variable named ref_count should be incremented.

Similarly, one can implement operator<< for this hypothetical class by using a tuply "copy" and "ostream_iterator", but one of the types involved is bound to be awkward and have a print function but no operator<<.

Emily

--------------------------------------------------------------------
mail2web - Check your email from the web at
http://mail2web.com/ .


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