[typeof] void return

There are two problems with void returns. 1. A couple of examples in documentation are inaccurate: main returns void. The fix is $ cd $BOOST_ROOT/libs/typeof/doc $ sed 's/void main/int main/' typeof.qbk 2. BOOST_TYPEOF can't be applied to an expression returning void. void foo() {} int main() { BOOST_TYPEOF(foo()); // Error: ensure_obj doesn't accept void as an argument. } The patch below fixes this problem. It's built around comma operator: struct void_ {}; template<class T> T& operator,(T const&, void_); template<class T> T& ensure_obj(const T&); void ensure_obj(void_); Return type of an expression ((expr), void_()) is T&, if typeof(expr) == T && T != void void_, if typeof(expr) == void I ran tests on gcc 3.4.4 under FreeBSD. All tests passed. I haven't tried to analyze the problem on MSVC. Let me know if fixes are fine and I'll commit them. $ cvs diff -u boost/typeof/typeof.hpp alnsn@cvs.sourceforge.net's password: Index: boost/typeof/typeof.hpp =================================================================== RCS file: /cvsroot/boost/boost/boost/typeof/typeof.hpp,v retrieving revision 1.3 diff -u -r1.3 typeof.hpp --- boost/typeof/typeof.hpp 28 Sep 2005 03:47:05 -0000 1.3 +++ boost/typeof/typeof.hpp 3 Jan 2006 21:51:47 -0000 @@ -128,10 +128,15 @@ # ifndef MSVC_TYPEOF_HACK namespace boost { namespace type_of { + struct void_ {}; + template<class T> T& operator,(T const&, void_); template<class T> T& ensure_obj(const T&); + void ensure_obj(void_); }} -# define BOOST_TYPEOF(expr) BOOST_TYPEOF_KEYWORD(boost::type_of::ensure_obj(expr)) +# define BOOST_TYPEOF(expr) BOOST_TYPEOF_KEYWORD( \ + boost::type_of::ensure_obj( ((expr), boost::type_of::void_()) ) \ + ) # define BOOST_TYPEOF_TPL BOOST_TYPEOF # endif # define BOOST_TYPEOF_REGISTER_TYPE(x)

On 1/3/06, Alexander Nasonov <alnsn@yandex.ru> wrote:
There are two problems with void returns.
1. A couple of examples in documentation are inaccurate: main returns void. The fix is
$ cd $BOOST_ROOT/libs/typeof/doc $ sed 's/void main/int main/' typeof.qbk
2. BOOST_TYPEOF can't be applied to an expression returning void.
void foo() {} int main() { BOOST_TYPEOF(foo()); // Error: ensure_obj doesn't accept void as an argument. }
The patch below fixes this problem. It's built around comma operator:
struct void_ {}; template<class T> T& operator,(T const&, void_);
How will this work if someone implements their own operator,? template<class T> T& operator,(const my_type&,const T&); if expr equals my_type, wouldn't this break typeof for my_type? Peder
template<class T> T& ensure_obj(const T&); void ensure_obj(void_);
Return type of an expression ((expr), void_()) is T&, if typeof(expr) == T && T != void void_, if typeof(expr) == void
I ran tests on gcc 3.4.4 under FreeBSD. All tests passed. I haven't tried to analyze the problem on MSVC.
Let me know if fixes are fine and I'll commit them.
$ cvs diff -u boost/typeof/typeof.hpp alnsn@cvs.sourceforge.net's password: Index: boost/typeof/typeof.hpp =================================================================== RCS file: /cvsroot/boost/boost/boost/typeof/typeof.hpp,v retrieving revision 1.3 diff -u -r1.3 typeof.hpp --- boost/typeof/typeof.hpp 28 Sep 2005 03:47:05 -0000 1.3 +++ boost/typeof/typeof.hpp 3 Jan 2006 21:51:47 -0000 @@ -128,10 +128,15 @@ # ifndef MSVC_TYPEOF_HACK
namespace boost { namespace type_of { + struct void_ {}; + template<class T> T& operator,(T const&, void_); template<class T> T& ensure_obj(const T&); + void ensure_obj(void_); }}
-# define BOOST_TYPEOF(expr) BOOST_TYPEOF_KEYWORD(boost::type_of::ensure_obj(expr)) +# define BOOST_TYPEOF(expr) BOOST_TYPEOF_KEYWORD( \ + boost::type_of::ensure_obj( ((expr), boost::type_of::void_()) ) \ + ) # define BOOST_TYPEOF_TPL BOOST_TYPEOF # endif # define BOOST_TYPEOF_REGISTER_TYPE(x)
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Peder Holt wrote:
On 1/3/06, Alexander Nasonov <alnsn@yandex.ru> wrote:
The patch below fixes this problem. It's built around comma operator:
struct void_ {}; template<class T> T& operator,(T const&, void_);
How will this work if someone implements their own operator,? template<class T> T& operator,(const my_type&,const T&);
if expr equals my_type, wouldn't this break typeof for my_type?
You're right. I should have added a special object to the left of expr: ( wrap_nonvoid_expr(), (expr), resolve_void() ).get() template<class T> struct wrapped_obj { T& get(); }; struct wrap_nonvoid_expr { template<class T> wrapped_obj<T> operator,(T const&); }; struct resolve_void { void get(); }; template<class T> wrapped_obj<T> operator,(wrapped_obj<T>, resolve_void); -- Alexander Nasonov

Peder Holt wrote:
On 1/3/06, Alexander Nasonov <alnsn@yandex.ru> wrote:
The patch below fixes this problem. It's built around comma operator:
struct void_ {}; template<class T> T& operator,(T const&, void_);
How will this work if someone implements their own operator,? template<class T> T& operator,(const my_type&,const T&);
if expr equals my_type, wouldn't this break typeof for my_type?
You're right. I should have added a special object to the left of expr: ( wrap_nonvoid_expr(), (expr), resolve_void() ).get() template<class T> struct wrapped_obj { T& get(); }; struct wrap_nonvoid_expr { template<class T> wrapped_obj<T> operator,(T const&); }; struct resolve_void { void get(); }; template<class T> wrapped_obj<T> operator,(wrapped_obj<T>, resolve_void); -- Alexander Nasonov

"Alexander Nasonov" <alnsn@yandex.ru> wrote
Peder Holt wrote:
On 1/3/06, Alexander Nasonov <alnsn@yandex.ru> wrote:
The patch below fixes this problem. It's built around comma operator:
struct void_ {}; template<class T> T& operator,(T const&, void_);
How will this work if someone implements their own operator,? template<class T> T& operator,(const my_type&,const T&);
if expr equals my_type, wouldn't this break typeof for my_type?
You're right. I should have added a special object to the left of expr:
( wrap_nonvoid_expr(), (expr), resolve_void() ).get()
template<class T> struct wrapped_obj { T& get(); };
struct wrap_nonvoid_expr { template<class T> wrapped_obj<T> operator,(T const&); };
struct resolve_void { void get(); };
template<class T> wrapped_obj<T> operator,(wrapped_obj<T>, resolve_void);
AFAIU, you are trying to fix ensure_obj, but this is only one context in which typeof would fail with void expression. The other contexts include: 1) typeof emulation; 2) MSVC trick; 3) LVALUE_TYPEOF All of the above try to pass the expression into a function, and will fail if type of the expression is void. Whichever solution we'll find, I think we should wrap it into a macro, and consistently apply everywhere. As far as what you suggesting, it looks promising, but we need to evaluate consiquenses... Such as one Peder found. Also there is at least one more case when something can't be bound to const T&, and this is MSVC-specific problem found on RSDN (see a couple of tests failing for vc-7_1). We'll have to see that the solution to the "void" problem works together with whichever MSVC workaround we apply... Regards, Arkadiy

Arkadiy Vertleyb wrote:
AFAIU, you are trying to fix ensure_obj, but this is only one context in which typeof would fail with void expression. The other contexts include:
1) typeof emulation; 2) MSVC trick; 3) LVALUE_TYPEOF
Yes.
All of the above try to pass the expression into a function, and will fail if type of the expression is void.
Whichever solution we'll find, I think we should wrap it into a macro, and consistently apply everywhere.
As far as what you suggesting, it looks promising, but we need to evaluate consiquenses... Such as one Peder found.
I agree. Another consequence is ICE on gcc 3.3.5 :( 3.4.4 is immune to my fix. -- Alexander Nasonov
participants (3)
-
Alexander Nasonov
-
Arkadiy Vertleyb
-
Peder Holt