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 ]