Topic: mem_fun_ref_t<...>::argument_type. What?


Author: sbnaran@localhost.localdomain.COM (Siemel Naran)
Date: 1998/12/21
Raw View
On 21 Dec 1998 17:18:29 GMT, Miniussi <miniussi@ilog.fr> wrote:
>Siemel Naran wrote:

>> But the whole problem could be solved by changing
>>    binder2nd(Oper oper, typename const Oper::second_argument_type&);
>> to
>>    binder2nd(Oper oper, typename Oper::second_argument_type);

>Which involves changing most of the predifined function object
>(plus, minus etc.).

No!  The builtin function objects stay the same, although chaning them
would be better for other reasons.  Consider std::plus, which in the
current standard is:

struct plus : public binary_function<T,T,T>
{
     T operator()(const T& lhs, const T& rhs) const { return lhs+rhs; }
};

Now what happens in this:
   bind2nd(mem_fun(std::plus<int>()),3);
The inheritance in std::plus sets second_argument_type==int.
Then binder2nd receives its second argument as
   "const second_argument_type&" or "const int&".

But if bind2nd were changed to receive the second arg as "second_argument_type"
Then the call to binder2nd still works but this time receives an "int"



However, my other post said that the inheritance from binary_function
or unary_function should match the types in operator().  This increases
the utility of functional objects in template functions, as clients
could make constructive use of the typdefs first_argument_type and
second_argument_type, without fear that the argument should really be
const second_argument_type&.  This means that std::plus should be,

struct plus : public binary_function<const T&, const T&, T>
{
     T operator()(const T& lhs, const T& rhs) const { return lhs+rhs; }
};


Second, the second arg of binder2nd should be "second_argument_type"
So for bind2nd(mem_fun(std::plus<int>()),3), the '3' is received as
a "const int&".



Pass by value might be better for symmetry though.  On a very
optimizing compiler, there should be no penalty for pass by value.
So this is my preferred change to <functional>.

struct plus : public binary_function<T,T,T>
{
     T operator()(const T lhs, const T rhs) const { return lhs+rhs; }
};

So for bind2nd(mem_fun(std::plus<int>()),3), the '3' is received as
a "int".



>It's seem that the standard allow type parameters
>of standard lib templates to be const (by putting the required exceptions
>to problematics rules (71.5, 8.3.2(1)), but not references (8.3.2(4))
>(but without really requiring it in a formal way ?)

Changing "&&" to mean "&" seems a little drastic.  It might have
adverse effects on other parts of the language.

--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: AllanW@my-dejanews.com
Date: 1998/12/22
Raw View
In article <slrn77t4so.s73.sbnaran@localhost.localdomain>,
  sbnaran@uiuc.edu wrote:
[Discussing references to references]
> Changing "&&" to mean "&" seems a little drastic.  It might have
> adverse effects on other parts of the language.

Well, the && token already has a different meaning. I'll
assume you meant a reference to a reference.

In which case, I must disagree. Taking a reference of a reference
is currently illegal, so no conforming programs do this. Giving
it a meaning cannot affect any programs that were already legal.

--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: sbnaran@localhost.localdomain.COM (Siemel Naran)
Date: 1998/12/22
Raw View
On 22 Dec 1998 19:51:04 GMT, AllanW@my-dejanews.com

>> Changing "&&" to mean "&" seems a little drastic.  It might have
>> adverse effects on other parts of the language.

>Well, the && token already has a different meaning. I'll
>assume you meant a reference to a reference.
>
>In which case, I must disagree. Taking a reference of a reference
>is currently illegal, so no conforming programs do this. Giving
>it a meaning cannot affect any programs that were already legal.

OK, but it's a conceptual change.

--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Miniussi <miniussi@ilog.fr>
Date: 1998/12/18
Raw View
Siemel Naran wrote:
>
> I also had a post about a similar problem in the constructor of
> class binder2nd.  In particular, it's second argument should not
> be a
>    const typename Oper::second_argument_type&
> but rather should be
>    typename Oper::second_argument_type
> because it is very possible that "second_argument_type" is
> already a reference and is const qualified.
>
> Can someone please shed light on this for me?  These seem to be
> two bugs in the standard.

I don't have the reference for references, but for const, the standard
says: (7.1.5)
[
 - const or volatile  can be combined with any other type-specifier.
However, redundant cv-qualifiers are prohibited _except_ when introduced
through the use of typedefs or template type argument, in which case the
redundant cv-qulifiers are ignored.
]

(otherwise, how could we use const on a template type parameter ?).

Alain


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: sbnaran@localhost.localdomain.COM (Siemel Naran)
Date: 1998/12/19
Raw View
On 18 Dec 1998 16:11:29 GMT, Miniussi <miniussi@ilog.fr> wrote:

>I don't have the reference for references, but for const, the standard
                  ^^^^^^^^^^^^^^^^^^^^^^^^ nice :)
>says: (7.1.5)


>[
> - const or volatile  can be combined with any other type-specifier.
>However, redundant cv-qualifiers are prohibited _except_ when introduced
>through the use of typedefs or template type argument, in which case the
>redundant cv-qulifiers are ignored.
>]

Fine.  My compilers actually give warning messages, and maybe the
next version will suppress the warnings.  The deeper problem seems
to be what to do with "&&".  I don't think the standard allows
ignoring this.

But the whole problem could be solved by changing
   binder2nd(Oper oper, typename const Oper::second_argument_type&);
to
   binder2nd(Oper oper, typename Oper::second_argument_type);


--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Miniussi <miniussi@ilog.fr>
Date: 1998/12/21
Raw View
Siemel Naran wrote:
>
> On 18 Dec 1998 16:11:29 GMT, Miniussi <miniussi@ilog.fr> wrote:
> Fine.  My compilers actually give warning messages, and maybe the
> next version will suppress the warnings.  The deeper problem seems
> to be what to do with "&&".  I don't think the standard allows
> ignoring this.
Right, 8.3.2(4) does says that && isn't allowed and does not mention
any exception to the rule. (which is strange, since the needed exception
is done for const const and for const A with A==T&)

> But the whole problem could be solved by changing
>    binder2nd(Oper oper, typename const Oper::second_argument_type&);
> to
>    binder2nd(Oper oper, typename Oper::second_argument_type);

Which involves changing most of the predifined function object
(plus, minus etc.).

It's seem that the standard allow type parameters
of standard lib templates to be const (by putting the required exceptions
to problematics rules (71.5, 8.3.2(1)), but not references (8.3.2(4))
(but without really requiring it in a formal way ?)

So, any light on this is actually welcome...

Alain



[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: sbnaran@localhost.localdomain.COM (Siemel Naran)
Date: 1998/12/17
Raw View
On 15 Dec 1998 21:24:32 GMT, Petter Urkedal <petter@matfys.lth.se> wrote:

>To elaborate on the point, SGI's STL defines a class with semantics as
>the following:
>
>    template<Fun1, Fun2>
>    struct unary_compose
> : unary_function< typename Fun2::argument_type,
>     typename Fun1::result_type > {
> typename Fun1::result_type
> operator()(typename Fun2::argument_type x) { return f(g(x)); }
>    private:
> Fun1 f;
> Fun2 g;
>    };
>
>If we use this for with `Fun2' = `mem_fun_ref_t<Result, Arg>', the type
>of the argument to `operator()' above will be `Arg', whereas the
>argument to `Fun2::operator()' will be `Arg&'.  As a consequence the
>`unary_compose' will copy its argument and pass the copy to `g' as a
>mutable reference.  This was surely not the intention, as changes to
>this object produced by `Fun2::operator()' will not be noticed on the
>argument passed to `operator()' in `unary_compose'.


Yes, this seems like a problem, possibly an error in the standard.
For function adaptors, because the op() function is
   Result operator()(Struct&, Parameter) const;
the inheritance of mem_fun from binary_function should not be
       : public binary_function<Struct,Parameter,Result>
but instead it should be
       : public binary_function<Struct&,Parameter,Result>

Simlar remarks hold for const_mem_func_t.

I also had a post about a similar problem in the constructor of
class binder2nd.  In particular, it's second argument should not
be a
   const typename Oper::second_argument_type&
but rather should be
   typename Oper::second_argument_type
because it is very possible that "second_argument_type" is
already a reference and is const qualified.


Can someone please shed light on this for me?  These seem to be
two bugs in the standard.

--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Petter Urkedal <petter@matfys.lth.se>
Date: 1998/12/15
Raw View
>>If it didn't matter, I wouldn't mind.  However, when using
>>mem_fun_ref_t<...>::result_type to handle an object before it is passed
>>to the functor, it will be copied, err.  But that's what adaptors are
>>for, to make the context `adapt' to the functions!  And it doesn't do
>>the job.

>I have no idea what you're talking about, but it seems that you want
>to use the traits "first_argument_type" and "second_argument_type".
>So they had better be correct.

Yes, I meant `first_argument_type', not `result_type'. Thanks.

To elaborate on the point, SGI's STL defines a class with semantics as
the following:

    template<Fun1, Fun2>
    struct unary_compose
 : unary_function< typename Fun2::argument_type,
     typename Fun1::result_type > {
 typename Fun1::result_type
 operator()(typename Fun2::argument_type x) { return f(g(x)); }
    private:
 Fun1 f;
 Fun2 g;
    };

If we use this for with `Fun2' = `mem_fun_ref_t<Result, Arg>', the type
of the argument to `operator()' above will be `Arg', whereas the
argument to `Fun2::operator()' will be `Arg&'.  As a consequence the
`unary_compose' will copy its argument and pass the copy to `g' as a
mutable reference.  This was surely not the intention, as changes to
this object produced by `Fun2::operator()' will not be noticed on the
argument passed to `operator()' in `unary_compose'.

 -petter.

--
[- http://matfys.lth.se/~petter/ -]


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: sbnaran@localhost.localdomain.COM (Siemel Naran)
Date: 1998/12/13
Raw View
On 11 Dec 1998 17:53:23 GMT, Petter Urkedal <petter@matfys.lth.se> wrote:


>    template <class S, class T, class A> class mem_fun1_ref_t
>          : public binary_function<T, A, S> {
>    public:
>      explicit mem_fun1_ref_t(S (T::*p)(A));
>      S operator()(T& p, A x);
>    };

>and similar for mem_fun_ref_t.

template <class Result, class Object, class Arg> inline
mem_fun1_ref_t<Result,Object,Arg>
mem_fun_ref(Result (Object::*func)(Arg) const)
{
     return mem_fun1_ref_t<Result,Object,Arg>(func);
}


>The first argument to this functional is `T&', but, as you can se it is
>also `T' according to the typedef of the public base class.  Can this
>really be so?  You may try to convince me that `const T&'==`T'; but
>`T&'==`T'?  No way.

Good point.

It seems to me that the ideal definition of mem_fun1_ref_t should use
the typedefs defined in binary_function.  In practice, we don't have
to do this much typing.  Here is the ideal:

    template <class S, class T, class A> class mem_fun1_ref_t
          : public binary_function<T, A, S> {
    typedef binary_function<T, A, S> base;
    public:
      typedef typename base::first_argument_type  first_argument_type ;
      typedef typename base::second_argument_type second_argument_type;
      typedef typename base::result_type          result_type         ;

      explicit mem_fun1_ref_t(S (T::*p)(A));
      result_type operator()(first_argument_type p, second_argument_type x);
      //S operator()(T& p, A x);
    };

If the types of operator() are "first_argument_type" and
"second_argument_type", and not "first_argument_type&" or whatever,
this enhances the use of the traits in generic template functions.

For example,

template <class UnaryFunction>
void generic_function(UnaryFunction);
  // can rely on traits argument_type and result_type
  // being properly defined


This means that the derivation from std::binary_function should be
          : public binary_function<T&, A, S> {




>If it didn't matter, I wouldn't mind.  However, when using
>mem_fun_ref_t<...>::result_type to handle an object before it is passed
>to the functor, it will be copied, err.  But that's what adaptors are
>for, to make the context `adapt' to the functions!  And it doesn't do
>the job.

I have no idea what you're talking about, but it seems that you want
to use the traits "first_argument_type" and "second_argument_type".
So they had better be correct.



>Is this changed in the standard?  Otherwise, can someone explain why
>the typedef is chosen such in the first place?

No, what you quoted above is the same as in the current standard.
It appears to me that the derivation should be
           : public binary_function<T&, A, S> {



--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Petter Urkedal <petter@matfys.lth.se>
Date: 1998/12/11
Raw View
Function adaptors unify functions and member functions into the same
kind of objects, making them `adapt' into various contexts through the
typedefs.  Very useful.  But this one have give me a headache:

CD2, 20.3.8--5:

    template <class S, class T, class A> class mem_fun1_ref_t
          : public binary_function<T, A, S> {
    public:
      explicit mem_fun1_ref_t(S (T::*p)(A));
      S operator()(T& p, A x);
    };

and similar for mem_fun_ref_t.

The first argument to this functional is `T&', but, as you can se it is
also `T' according to the typedef of the public base class.  Can this
really be so?  You may try to convince me that `const T&'==`T'; but
`T&'==`T'?  No way.

If it didn't matter, I wouldn't mind.  However, when using
mem_fun_ref_t<...>::result_type to handle an object before it is passed
to the functor, it will be copied, err.  But that's what adaptors are
for, to make the context `adapt' to the functions!  And it doesn't do
the job.

Is this changed in the standard?  Otherwise, can someone explain why
the typedef is chosen such in the first place?

 -petter.

--
[- http://matfys.lth.se/~petter/ -]


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]