
It seems to me that when BOOST_TYPEOF becomes available, boost::result_of should use it in its default implementation, something like: template <class F, class A> struct result_of<F(A)> { typedef typename BOOST_TYPEOF(make<F>() ( make<A>() ) ) type; }; Is that in the plan? -- Dave Abrahams Boost Consulting www.boost-consulting.com

On Jun 9, 2005, at 11:49 AM, David Abrahams wrote:
It seems to me that when BOOST_TYPEOF becomes available, boost::result_of should use it in its default implementation, something like:
template <class F, class A> struct result_of<F(A)> { typedef typename BOOST_TYPEOF(make<F>() ( make<A>() ) ) type; };
Is that in the plan?
Absolutely. Doug

On Jun 9, 2005, at 12:18 PM, Douglas Gregor wrote:
On Jun 9, 2005, at 11:49 AM, David Abrahams wrote:
It seems to me that when BOOST_TYPEOF becomes available, boost::result_of should use it in its default implementation, something like:
template <class F, class A> struct result_of<F(A)> { typedef typename BOOST_TYPEOF(make<F>() ( make<A>() ) ) type; };
Is that in the plan?
Absolutely.
The TR spec says that the implementation can use whatever means to determine the member type type that produces the exact type, and if it cannot determine the exact type, then the specs details out its behavior: 1 If F is a function type, type is the return type of the function type F. 2 If F is a member function type, type is the return type of the member function type F. 3 If F is a function object defined by the standard library, the method of determining type is unspecified. 4 If F is a class type with a member type result_type, type is F::result_type. 5 If F is a class type with no member named result_type or if F::result_type is not a type: a If N=0 (no arguments), type is void. b If N>0, type is F::result<F(T1, T2, ..., TN)>::type. 6 Otherwise, the program is ill-formed. (Note, this was copy/pasted from the proposal, not from TR1, so the exact rules may now be different). So if F and A are not registered, then result_of should go and follow the list above? Jaakko

"jarvi" <jarvi@cs.tamu.edu> wrote
On Jun 9, 2005, at 12:18 PM, Douglas Gregor wrote:
On Jun 9, 2005, at 11:49 AM, David Abrahams wrote:
It seems to me that when BOOST_TYPEOF becomes available, boost::result_of should use it in its default implementation, something like:
template <class F, class A> struct result_of<F(A)> { typedef typename BOOST_TYPEOF(make<F>() ( make<A>() ) ) type; };
Is that in the plan?
Absolutely.
The TR spec says that the implementation can use whatever means to determine the member type type that produces the exact type, and if it cannot determine the exact type, then the specs details out its behavior:
1 If F is a function type, type is the return type of the function type F. 2 If F is a member function type, type is the return type of the member function type F. 3 If F is a function object defined by the standard library, the method of determining type is unspecified. 4 If F is a class type with a member type result_type, type is F::result_type. 5 If F is a class type with no member named result_type or if F::result_type is not a type: a If N=0 (no arguments), type is void. b If N>0, type is F::result<F(T1, T2, ..., TN)>::type. 6 Otherwise, the program is ill-formed.
(Note, this was copy/pasted from the proposal, not from TR1, so the exact rules may now be different).
So if F and A are not registered, then result_of should go and follow the list above?
I am not sure if you mean typeof registration, but if you do, neither F nor A need to be registered. What needs to be registered are types and templates that are present in the result type of F()(A()). Regards, Arkadiy

On Jun 9, 2005, at 1:11 PM, Arkadiy Vertleyb wrote:
I am not sure if you mean typeof registration, but if you do, neither F nor A need to be registered. What needs to be registered are types and templates that are present in the result type of F()(A()).
Hi Arkadiy, Sorry, my wording was a bit sloppy, thanks for clarifying. The main point was that the result_of template needs to detect whether the BOOST_TYPEOF will succeed (all relevant types/templates have been typeof-registered), and if it will not succeed, then follow the list of steps specified in the TR1. Cheers, Jaakko

"jarvi" <jarvi@cs.tamu.edu> wrote
The main point was that the result_of template needs to detect whether the BOOST_TYPEOF will succeed (all relevant types/templates have been typeof-registered), and if it will not succeed, then follow the list of steps specified in the TR1.
Well, I am afraid this might not be possible with current BOOST_TYPEOF --Types/templates not registerd just result in compile error :-( Come to think about it, this doesn't have to stay this way. I havn't tried it, but it seems possible to just put some well-known type in place of not-registered one, for example, something like this: "std::pair<std::vector<boost::type_of::not_registered>, int>" or maybe just "boost::type_of::not_registered" This way the fact that types are not registered can be used in meta-programs. The drawback -- it's unclear what's not registered. So maybe we need some sort of combination of both. Again, *I think* it's possible, but I am not in a position to verify this until later in the evening... Is it something that would be of interest? Regards, Arkadiy Regards, Arkadiy

On 6/9/05, Arkadiy Vertleyb <vertleyb@hotmail.com> wrote:
"jarvi" <jarvi@cs.tamu.edu> wrote
The main point was that the result_of template needs to detect whether the BOOST_TYPEOF will succeed (all relevant types/templates have been typeof-registered), and if it will not succeed, then follow the list of steps specified in the TR1.
Well, I am afraid this might not be possible with current BOOST_TYPEOF --Types/templates not registerd just result in compile error :-(
Come to think about it, this doesn't have to stay this way. I havn't tried it, but it seems possible to just put some well-known type in place of not-registered one, for example, something like this:
"std::pair<std::vector<boost::type_of::not_registered>, int>"
or maybe just
"boost::type_of::not_registered"
This way the fact that types are not registered can be used in meta-programs. The drawback -- it's unclear what's not registered. So maybe we need some sort of combination of both.
Again, *I think* it's possible, but I am not in a position to verify this until later in the evening... Is it something that would be of interest?
I did this once for the vintage implementation. Here is the technique I used: (Except I used function overloads...) namespace boost {namespace type_of{ namespace { struct not_registered_vector { typedef mpl::int_<1> item ## n; //For n=0 to BOOST_TYPEOF_LIMIT_SIZE }; template<typename T> struct push_back<not_registered_vector,T> { typedef not_registered_vector type; }; //Default implementation of encode_type_impl template<typename V,typename T> struct encode_type_impl { typedef uninitialized_type_vector type; }; struct not_registered {}; template<class Iter> struct decode_type_impl<mpl::size_t<1>, Iter> { typedef not_registered type; typedef Iter iter; }; }} If we place this code in a separate header file, we can trigger compile errors on demand. Regards, Peder
Regards, Arkadiy
Regards, Arkadiy
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On 6/9/05, Arkadiy Vertleyb <vertleyb@hotmail.com> wrote:
"jarvi" <jarvi@cs.tamu.edu> wrote
The main point was that the result_of template needs to detect whether the BOOST_TYPEOF will succeed (all relevant types/templates have been typeof-registered), and if it will not succeed, then follow the list of steps specified in the TR1.
Well, I am afraid this might not be possible with current BOOST_TYPEOF --Types/templates not registerd just result in compile error :-(
Come to think about it, this doesn't have to stay this way. I havn't
it, but it seems possible to just put some well-known type in place of not-registered one, for example, something like this:
"std::pair<std::vector<boost::type_of::not_registered>, int>"
or maybe just
"boost::type_of::not_registered"
This way the fact that types are not registered can be used in meta-programs. The drawback -- it's unclear what's not registered. So maybe we need some sort of combination of both.
Again, *I think* it's possible, but I am not in a position to verify
"Peder Holt" <peder.holt@gmail.com> wrote tried this
until later in the evening... Is it something that would be of interest?
I did this once for the vintage implementation. Here is the technique I used: (Except I used function overloads...)
namespace boost {namespace type_of{ namespace {
struct not_registered_vector { typedef mpl::int_<1> item ## n; //For n=0 to BOOST_TYPEOF_LIMIT_SIZE };
template<typename T> struct push_back<not_registered_vector,T> { typedef not_registered_vector type; };
//Default implementation of encode_type_impl template<typename V,typename T> struct encode_type_impl { typedef uninitialized_type_vector type; };
struct not_registered {}; template<class Iter> struct decode_type_impl<mpl::size_t<1>, Iter> { typedef not_registered type; typedef Iter iter; };
}}
If we place this code in a separate header file, we can trigger compile errors on demand.
Actually what I meant is even simpler, something like: given desired results: 1) "std::pair<std::vector<boost::type_of::not_registered>, int>" 2) "boost::type_of::not_registered" namespace boost { namespace type_of { srtuct not_registered; }} BOOST_TYPEOF_REGISTER_TYPE(not_registered) namespace boost { namespace type_of { template<class V, class T> struct encode_type_impl // default impl { typedef typename encode_type_impl<V, not_registered>::type type; }; }} should achieve the result #1. To achieve the result #2 there seem to be a few alternatives. But again, I would first like to know if this would be useful. Regards, Arkadiy

On 6/10/05, Arkadiy Vertleyb <vertleyb@hotmail.com> wrote:
"Peder Holt" <peder.holt@gmail.com> wrote
"jarvi" <jarvi@cs.tamu.edu> wrote
The main point was that the result_of template needs to detect whether the BOOST_TYPEOF will succeed (all relevant types/templates have been typeof-registered), and if it will not succeed, then follow the list of steps specified in the TR1.
Well, I am afraid this might not be possible with current BOOST_TYPEOF --Types/templates not registerd just result in compile error :-(
Come to think about it, this doesn't have to stay this way. I havn't
it, but it seems possible to just put some well-known type in place of not-registered one, for example, something like this:
"std::pair<std::vector<boost::type_of::not_registered>, int>"
or maybe just
"boost::type_of::not_registered"
This way the fact that types are not registered can be used in meta-programs. The drawback -- it's unclear what's not registered. So maybe we need some sort of combination of both.
Again, *I think* it's possible, but I am not in a position to verify
On 6/9/05, Arkadiy Vertleyb <vertleyb@hotmail.com> wrote: tried this
until later in the evening... Is it something that would be of interest?
I did this once for the vintage implementation. Here is the technique I used: (Except I used function overloads...)
namespace boost {namespace type_of{ namespace {
struct not_registered_vector { typedef mpl::int_<1> item ## n; //For n=0 to BOOST_TYPEOF_LIMIT_SIZE };
template<typename T> struct push_back<not_registered_vector,T> { typedef not_registered_vector type; };
//Default implementation of encode_type_impl template<typename V,typename T> struct encode_type_impl { typedef uninitialized_type_vector type; };
struct not_registered {}; template<class Iter> struct decode_type_impl<mpl::size_t<1>, Iter> { typedef not_registered type; typedef Iter iter; };
}}
If we place this code in a separate header file, we can trigger compile errors on demand.
Actually what I meant is even simpler, something like:
given desired results: 1) "std::pair<std::vector<boost::type_of::not_registered>, int>" 2) "boost::type_of::not_registered"
namespace boost { namespace type_of { srtuct not_registered; }}
BOOST_TYPEOF_REGISTER_TYPE(not_registered)
namespace boost { namespace type_of { template<class V, class T> struct encode_type_impl // default impl { typedef typename encode_type_impl<V, not_registered>::type type; }; }}
should achieve the result #1. To achieve the result #2 there seem to be a few alternatives.
But again, I would first like to know if this would be useful.
As a user of typeof, I would certainly find this very useful. It allows the programmer to take evasive action if the typeof operation fails, by finding a suitable type in another way. #1 would not help me here. #2, on the other hand, allows me check if the type 'returned' by typeof is not_registered. If it is, one can programatically work around it. my suggestion would yield #2 Another useful feature, would be to detect if an expression is too complex. If an expression has a complexity>BOOST_TYPEOF_LIMIT_SIZE, typeof should 'return' boost::type_of::type_too_complex or similar. This can be achieved in a similar way to what I suggested earlier. Regards, Peder
Regards, Arkadiy
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

"Peder Holt" <peder.holt@gmail.com> wrote
As a user of typeof, I would certainly find this very useful. It allows the programmer to take evasive action if the typeof operation fails, by finding a suitable type in another way.
Well, as the discussion about result_of shows, it might make sense. Although, I think, for 99% of uses one just wants the compiler to show which types need to be registered.
#1 would not help me here. #2, on the other hand, allows me check if the type 'returned' by typeof is not_registered. If it is, one can programatically work around it.
my suggestion would yield #2
OK, agreed.
Another useful feature, would be to detect if an expression is too complex. If an expression has a complexity>BOOST_TYPEOF_LIMIT_SIZE, typeof should 'return' boost::type_of::type_too_complex or similar.
This can be achieved in a similar way to what I suggested earlier.
Right. Let's just say it can be done if there is a specific request for this. I would not like to add any features that are not going to be used. Regards, Arkadiy

On Jun 9, 2005, at 12:40 PM, jarvi wrote:
On Jun 9, 2005, at 12:18 PM, Douglas Gregor wrote:
On Jun 9, 2005, at 11:49 AM, David Abrahams wrote:
It seems to me that when BOOST_TYPEOF becomes available, boost::result_of should use it in its default implementation, something like:
template <class F, class A> struct result_of<F(A)> { typedef typename BOOST_TYPEOF(make<F>() ( make<A>() ) ) type; };
Is that in the plan?
Absolutely.
The TR spec says that the implementation can use whatever means to determine the member type type that produces the exact type, and if it cannot determine the exact type, then the specs details out its behavior:
1 If F is a function type, type is the return type of the function type F. 2 If F is a member function type, type is the return type of the member function type F. 3 If F is a function object defined by the standard library, the method of determining type is unspecified. 4 If F is a class type with a member type result_type, type is F::result_type. 5 If F is a class type with no member named result_type or if F::result_type is not a type: a If N=0 (no arguments), type is void. b If N>0, type is F::result<F(T1, T2, ..., TN)>::type. 6 Otherwise, the program is ill-formed.
(Note, this was copy/pasted from the proposal, not from TR1, so the exact rules may now be different).
So if F and A are not registered, then result_of should go and follow the list above?
Yes, that sounds like the right way to handle things. Doug

jarvi <jarvi@cs.tamu.edu> writes:
On Jun 9, 2005, at 12:18 PM, Douglas Gregor wrote:
On Jun 9, 2005, at 11:49 AM, David Abrahams wrote:
It seems to me that when BOOST_TYPEOF becomes available, boost::result_of should use it in its default implementation, something like:
template <class F, class A> struct result_of<F(A)> { typedef typename BOOST_TYPEOF(make<F>() ( make<A>() ) ) type; };
Is that in the plan?
Absolutely.
The TR spec says that the implementation can use whatever means to determine the member type type that produces the exact type, and if it cannot determine the exact type, then the specs details out its behavior:
1 If F is a function type, type is the return type of the function type F. 2 If F is a member function type, type is the return type of the member function type F.
These two are redundant. That *is* the exact type, so the implementation can determine it.
3 If F is a function object defined by the standard library, the method of determining type is unspecified. 4 If F is a class type with a member type result_type, type is F::result_type. 5 If F is a class type with no member named result_type or if F::result_type is not a type: a If N=0 (no arguments), type is void. b If N>0, type is F::result<F(T1, T2, ..., TN)>::type.
6 Otherwise, the program is ill-formed.
Seems to me that the whole behavior we need for the primary boost::result_of template is: 1 If F is a function type, type is the return type of the function type F. 2 If F is a member function type, type is the return type of the member function type F. 3 If BOOST_TYPEOF knows the result type of the expression, that is type. Note that we're on slightly shaky ground here because we'll mis-report const lvalues as rvalues... unless someone can figure out how to apply Eric N.'s ?: discoveries to know for sure. The above steps constitute "using whatever means to determine the exact type." 4 If F is a class type with a member type result_type, type is F::result_type. 5 If F is a class type with no member named result_type or if F::result_type is not a type: a If N=0 (no arguments), type is void. b If N>0, type is F::result<F(T1, T2, ..., TN)>::type. 6 Otherwise, the program is ill-formed. -- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote
3 If BOOST_TYPEOF knows the result type of the expression, that is type. Note that we're on slightly shaky ground here because we'll mis-report const lvalues as rvalues... unless someone can figure out how to apply Eric N.'s ?: discoveries to know for sure.
Just to make sure that we are on the same page, did you mean we mis-report const non-references as const lvalues? For example, if a function is declared as "const int foo()" (which makes little sense to me, but possible), LVALUE_TYPEOF would yield: "const int&". In case of a function declared as "const int& foo()", LVALUE_TYPEOF would correctly produce "const int&". Regards, Arkadiy

"Arkadiy Vertleyb" <vertleyb@hotmail.com> writes:
"David Abrahams" <dave@boost-consulting.com> wrote
3 If BOOST_TYPEOF knows the result type of the expression, that is type. Note that we're on slightly shaky ground here because we'll mis-report const lvalues as rvalues... unless someone can figure out how to apply Eric N.'s ?: discoveries to know for sure.
Just to make sure that we are on the same page, did you mean we mis-report const non-references as const lvalues? For example, if a function is declared as "const int foo()" (which makes little sense to me, but possible), LVALUE_TYPEOF would yield: "const int&".
Yes, that's what I meant. I'm more concerned with returning const class types, for what it's worth. Note that since you *do* have a runtime expression, it seems like Eric's technique might apply here. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
"Arkadiy Vertleyb" <vertleyb@hotmail.com> writes:
Just to make sure that we are on the same page, did you mean we mis-report const non-references as const lvalues? For example, if a function is declared as "const int foo()" (which makes little sense to me, but possible), LVALUE_TYPEOF would yield: "const int&".
Yes, that's what I meant. I'm more concerned with returning const class types, for what it's worth.
As well you should be :-) because rvalues of non-class types are never cv-qualified, 3.10/9.

"Peter Dimov" <pdimov@mmltd.net> writes:
David Abrahams wrote:
"Arkadiy Vertleyb" <vertleyb@hotmail.com> writes:
Just to make sure that we are on the same page, did you mean we mis-report const non-references as const lvalues? For example, if a function is declared as "const int foo()" (which makes little sense to me, but possible), LVALUE_TYPEOF would yield: "const int&".
Yes, that's what I meant. I'm more concerned with returning const class types, for what it's worth.
As well you should be :-) because rvalues of non-class types are never cv-qualified, 3.10/9.
Why else would I be more concerned with class types? :-) -- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote
template <class F, class A> struct result_of<F(A)> { typedef typename BOOST_TYPEOF(make<F>() ( make<A>() ) ) type; };
BTW, I was having (not typeof-related) problems trying to achieve this kind of syntax in VC7.1 :-( http://lists.boost.org/boost/2005/06/27892.php "make<F>()(make<A>())" just doesn't work. The only thing that kind of works (but with a warning) is "F()(make<A>())". Am I missing something? Regards, Arkadiy

On Jun 9, 2005, at 12:53 PM, Arkadiy Vertleyb wrote:
"David Abrahams" <dave@boost-consulting.com> wrote
template <class F, class A> struct result_of<F(A)> { typedef typename BOOST_TYPEOF(make<F>() ( make<A>() ) ) type; };
BTW, I was having (not typeof-related) problems trying to achieve this kind of syntax in VC7.1 :-(
http://lists.boost.org/boost/2005/06/27892.php
"make<F>()(make<A>())" just doesn't work. The only thing that kind of works (but with a warning) is "F()(make<A>())".
Am I missing something?
Should that be "make<F&>"? For workarounds, we could also declare a static member of type F. Doug

"Doug Gregor" <dgregor@cs.indiana.edu> wrote
On Jun 9, 2005, at 12:53 PM, Arkadiy Vertleyb wrote:
"David Abrahams" <dave@boost-consulting.com> wrote
template <class F, class A> struct result_of<F(A)> { typedef typename BOOST_TYPEOF(make<F>() ( make<A>() ) ) type; };
BTW, I was having (not typeof-related) problems trying to achieve this kind of syntax in VC7.1 :-(
http://lists.boost.org/boost/2005/06/27892.php
"make<F>()(make<A>())" just doesn't work. The only thing that kind of works (but with a warning) is "F()(make<A>())".
Am I missing something?
Should that be "make<F&>"? For workarounds, we could also declare a static member of type F.
The following doesn't compile in VC7.1: template<int n> struct int_; template<class T> T make(); template<class F> int_<sizeof( (make<F&>())() )> foo(); int main() { } Regards, Arkadiy

"Arkadiy Vertleyb" <vertleyb@hotmail.com> writes:
"Doug Gregor" <dgregor@cs.indiana.edu> wrote
On Jun 9, 2005, at 12:53 PM, Arkadiy Vertleyb wrote:
"David Abrahams" <dave@boost-consulting.com> wrote
template <class F, class A> struct result_of<F(A)> { typedef typename BOOST_TYPEOF(make<F>() ( make<A>() ) ) type; };
BTW, I was having (not typeof-related) problems trying to achieve this kind of syntax in VC7.1 :-(
http://lists.boost.org/boost/2005/06/27892.php
"make<F>()(make<A>())" just doesn't work. The only thing that kind of works (but with a warning) is "F()(make<A>())".
Am I missing something?
Should that be "make<F&>"? For workarounds, we could also declare a static member of type F.
The following doesn't compile in VC7.1:
template<int n> struct int_; template<class T> T make();
template<class F> int_<sizeof( (make<F&>())() )> foo();
int main() { }
Try: template<int n> struct int_; template<class T> struct made { static T value; }; template<class F> int_<sizeof( made<F&>::value () )> foo(); int main() { } -- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote
Try:
template<int n> struct int_; template<class T> struct made { static T value; };
template<class F> int_<sizeof( made<F&>::value () )> foo();
int main() { }
The same result in VC7.1: "term does not evaluate to a function taking 0 arguments" Regards, Arkadiy

Doug Gregor <dgregor@cs.indiana.edu> writes:
On Jun 9, 2005, at 12:53 PM, Arkadiy Vertleyb wrote:
"David Abrahams" <dave@boost-consulting.com> wrote
template <class F, class A> struct result_of<F(A)> { typedef typename BOOST_TYPEOF(make<F>() ( make<A>() ) ) type; };
BTW, I was having (not typeof-related) problems trying to achieve this kind of syntax in VC7.1 :-(
http://lists.boost.org/boost/2005/06/27892.php
"make<F>()(make<A>())" just doesn't work. The only thing that kind of works (but with a warning) is "F()(make<A>())".
Am I missing something?
Should that be "make<F&>"?
Probably make<typename add_reference<F>::type>() Note "something like" above.
For workarounds, we could also declare a static member of type F.
Yeah. Or maybe add more parens ( make<typename add_reference<F>::type>() )( make<A>() ) -- Dave Abrahams Boost Consulting www.boost-consulting.com
participants (7)
-
Arkadiy Vertleyb
-
David Abrahams
-
Doug Gregor
-
Douglas Gregor
-
jarvi
-
Peder Holt
-
Peter Dimov