Topic: can functions returning void be used in the various mem_fun_t variants?


Author: the_wid@my-deja.com (Tom)
Date: 2000/09/20
Raw View
On Tue, 19 Sep 2000 16:24:36 GMT, the_wid@my-deja.com (Tom) wrote:
>>template <class T> class mem_fun_t
>
>insert
><T, void>
>after mem_fun_t

Correction: I meant <void, T>

Tom

---
[ 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: the_wid@my-deja.com (Tom)
Date: 2000/09/19
Raw View
On Fri,  8 Sep 2000 15:33:07 GMT, "Jeff Greif"
<jgreif@spam-me-not.befree.com> wrote:

>Given
>class Foo {
>  public:
>  void bar();
>};
>
>if you use mem_fun(&Foo::bar), a class mem_fun_t<void, Foo> is created which
>has a member void operator()(Foo*).  In the Dinkumware implementation (v.
>2.33), there is something like this
>
>template <class Ret, class T> class mem_fun_t : public unary_function<T,Ret>
>{
>public:
>  mem_fun_t(Ret (T::*Memptr)()) : ptr_(Memptr) {}
>  Ret operator()(T* p) const { return (p->*ptr_)(); }
>private:
>  Ret (T::*ptr_)();
>};
>
>and the compiler (MSVC++6 SP3) complains that returning a value from the
>operator() is illegal when Ret is void.

An MSVC problem. The code should work.

>
>I can work around this by derivation:
>template <class T> class void_mem_fun_t : public mem_fun_t<void,T> {
>public:
>  void_mem_fun_t(void (T::*Memptr)()) : mem_fun_t<void,T>(Memptr) {}
>  void operator()(T* p) const {  (p->*ptr_)(); return;}
>private:
>  void (T::*ptr_)();
>};
>but this seems a kludge, since you also have to produce new template
>convenience functions to generate these derived templates, like this:
>template<class _Ty> inline
> void_mem_fun_t<_Ty> void_mem_fun(void (_Ty::*_Pm)())
> {return (void_mem_fun_t<_Ty>(_Pm)); }
>
>Possibly, the original problem could be an implementation bug.  I tried
>fixing it by partially specializing the template (at the moment I can't tell
>whether this is legal because the same compiler will not handle it and is
>perhaps right):

MSVC can't handle partial specialization.

>
>template <class T> class mem_fun_t

insert
<T, void>
after mem_fun_t

 : public unary_function<T,void> {
>public:
>  mem_fun_t(void (T::*Memptr)()) : ptr_(Memptr) {}
>  void operator()(T* p) const {  (p->*ptr_)(); return;}
>private:
>  void (T::*ptr_)();
>};

That should have worked, and does work in gcc, although it is
unnecessary.

>
>Another possibility is that the compiler could be incorrectly producing an
>error; that is,
>  return expr;
>where the type of expr is void could be considered equivalent to
>  expr; return;
>
>How does the standard address this issue?

The following code is allowed by the standard:

void g()
{
}

void f()
{
    return g();
}

MSVC doesn't like it.

Before you go down that path of using mem_fun, may I recommend that
you download STLport from www.stlport.org. The <functional> header in
the MSVC standard lib (by Dinkumware) is very out of date, and
contains at least one bug. The bug is:

// TEMPLATE CLASS mem_fun1_ref_t
template<class _R, class _Ty, class _A>
- class mem_fun1_ref_t : public binary_function<_Ty *, _A, _R> {
+ class mem_fun1_ref_t : public binary_function<_Ty, _A, _R> {

removing the * from _Ty*.

I have no doubt that the current Dinkumware lib has this fixed, since
it has been updated (long ago now) to reflect late changes in
<functional> before it was standardized. The late changes in the
standard seem to be vital, since they allow such things as use of
const member functions with mem_fun, etc, etc. STLport includes all
these, plus a couple of extensions (like binary_compose) which I think
could be done better, as at www.boost.org.

Tom

---
[ 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: "Jeff Greif" <jgreif@spam-me-not.befree.com>
Date: Fri, 8 Sep 2000 15:33:07 GMT
Raw View
Given
class Foo {
  public:
  void bar();
};

if you use mem_fun(&Foo::bar), a class mem_fun_t<void, Foo> is created which
has a member void operator()(Foo*).  In the Dinkumware implementation (v.
2.33), there is something like this

template <class Ret, class T> class mem_fun_t : public unary_function<T,Ret>
{
public:
  mem_fun_t(Ret (T::*Memptr)()) : ptr_(Memptr) {}
  Ret operator()(T* p) const { return (p->*ptr_)(); }
private:
  Ret (T::*ptr_)();
};

and the compiler (MSVC++6 SP3) complains that returning a value from the
operator() is illegal when Ret is void.

I can work around this by derivation:
template <class T> class void_mem_fun_t : public mem_fun_t<void,T> {
public:
  void_mem_fun_t(void (T::*Memptr)()) : mem_fun_t<void,T>(Memptr) {}
  void operator()(T* p) const {  (p->*ptr_)(); return;}
private:
  void (T::*ptr_)();
};
but this seems a kludge, since you also have to produce new template
convenience functions to generate these derived templates, like this:
template<class _Ty> inline
 void_mem_fun_t<_Ty> void_mem_fun(void (_Ty::*_Pm)())
 {return (void_mem_fun_t<_Ty>(_Pm)); }

Possibly, the original problem could be an implementation bug.  I tried
fixing it by partially specializing the template (at the moment I can't tell
whether this is legal because the same compiler will not handle it and is
perhaps right):

template <class T> class mem_fun_t : public unary_function<T,void> {
public:
  mem_fun_t(void (T::*Memptr)()) : ptr_(Memptr) {}
  void operator()(T* p) const {  (p->*ptr_)(); return;}
private:
  void (T::*ptr_)();
};

Another possibility is that the compiler could be incorrectly producing an
error; that is,
  return expr;
where the type of expr is void could be considered equivalent to
  expr; return;

How does the standard address this issue?

Jeff

---
[ 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: James Kuyper <kuyper@wizard.net>
Date: Fri, 8 Sep 2000 22:21:22 GMT
Raw View
Jeff Greif wrote:
>
> Given
> class Foo {
>   public:
>   void bar();
> };
>
> if you use mem_fun(&Foo::bar), a class mem_fun_t<void, Foo> is created which
> has a member void operator()(Foo*).  In the Dinkumware implementation (v.
> 2.33), there is something like this
>
> template <class Ret, class T> class mem_fun_t : public unary_function<T,Ret>
> {
> public:
>   mem_fun_t(Ret (T::*Memptr)()) : ptr_(Memptr) {}
>   Ret operator()(T* p) const { return (p->*ptr_)(); }
> private:
>   Ret (T::*ptr_)();
> };
>
> and the compiler (MSVC++6 SP3) complains that returning a value from the
> operator() is illegal when Ret is void.

It was precisely to cover this case that the standard contains the
following words in section 6.6.3p3: "A return statement with an
expression of type "_cv_ void" can be used only in functions with a
return type of _cv_ void; the expression is evaluated just before the
function returns to its caller."

You're using a non-conforming implementation.

...
> Another possibility is that the compiler could be incorrectly producing an
> error; that is,
>   return expr;
> where the type of expr is void could be considered equivalent to
>   expr; return;
>
> How does the standard address this issue?

Exactly as you've indicated.

---
[ 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              ]