
Hi all, Peder and I have put together a combined version of our typeof implementations. The integrated library supports both compliant and vintage compilers, and can be found in the Boost sandbox CVS (boost/typeof, libs/typeof) or at: http://groups.yahoo.com/group/boost/files/typeof_integrated.zip As always, any comments are most welcome. Regards, Arkadiy

I read the following from the documents: =================================== The BOOST_TYPEOF_REGISTER_TEMPLATE_X macro accepts a template name and a preprocessor sequence describing template parameters, where each parameter should be described as one of the following: § class § typename § [unsigned] char § [unsigned] short § [unsigned] int § [unsigned] long § unsigned § bool For example: BOOST_TYPEOF_REGISTER_TEMPLATE_X(foo, (class)(unsigned int)(bool)); =================================== I wonder if other non-type template parameter is supported. For example: template <void (*)()> struct template_with_func_ptr_param {}; BOOST_TYPEOF_REGISTER_TEMPLATE_X( template_with_func_ptr_param, (void (*)()) ); // is this legal or possible? template <void (MyClass::*)(int)> struct template_with_mem_func_ptr_param {}; BOOST_TYPEOF_REGISTER_TEMPLATE_X( template_with_mem_func_ptr_param, (void (MyClass::*)(int)) ); // is this legal or possible? template <typename T, T t> struct template_with_dependent_non_type_param {}; BOOST_TYPEOF_REGISTER_TEMPLATE_X( template_with_dependent_non_type_param, (class)(/* what to put here? */)) ); // is this legal or possible? I didn't look into the implementation of the library. If I am missing something, please don't hesitate to point it out. Best regards, Allen

Hi Allen,
I wonder if other non-type template parameter is supported. For example:
Unfortunately no -- all we support is type and integral template parameters. The implementation is based on the ability to encode a type as an array of compile-time integers. Therefore, in order to support other non-type template parameters we would have to find a way to somehow convert them into compile-time integers. So far I don't see a satisfactory way of achieving this :( Regards, Arkadiy

Unfortunately no -- all we support is type and integral template
Two more questions: (1) Is template template parameter supported? (2) In your opinion, is it just *possible* to support complex non-type template parameters suppose no matter how ugly the user interface will be? In addition, I suggest adding a section in the document of the typeof library to mention the problems about complex non-type template parameters, dependendent non-type template parameters and template template parameters, including whether they are supported or not by the current library, and the possibility or main obstacles for supporting them in the future. parameters.
The implementation is based on the ability to encode a type as an array of compile-time integers. Therefore, in order to support other non-type template parameters we would have to find a way to somehow convert them
into
compile-time integers. So far I don't see a satisfactory way of achieving this :(
Regards,
Arkadiy
Regards, Yao, Zhen

"Allen Yao" <yaozhen@ustc.edu> wrote
(1) Is template template parameter supported?
They aren't.
(2) In your opinion, is it just *possible* to support complex non-type template parameters suppose no matter how ugly the user interface will be?
It all depends on: 1) whether it is possible to represent this as a number of compile-time integers, and 2) whether it's possible to return this as a result of a meta-function. As far as my knowledge of the current state of template meta-programming goes, I don't see how it's possible. OTOH, 3 months ago I thought integral template parameters are impossible to support. And now, thanks to Peder, we do have them :).
In addition, I suggest adding a section in the document of the typeof library to mention the problems about complex non-type template parameters, dependendent non-type template parameters and template template parameters, including whether they are supported or not by the current library, and the possibility or main obstacles for supporting them in the future.
Good idea. Actually there is one more limitation that keeps bothering me. It is related to nested classes, and most unfortunate because of iterators. IOW, we can't just register, e.g., std::vector<T>::const_iterator (as we do with std::vector<T>), and the user always have to register concrete classes, like std::vector<int>::const_iterator, std::vector<short>::const_iterator, etc., separately, as she needs them. This limitation comes from the "non-deduced context", and applies at least to the compliant implementation, but I think the vintage implementation should have the same problem :( Regards, Arkadiy

On Wed, 1 Dec 2004 21:21:02 -0800, Arkadiy Vertleyb <vertleyb@hotmail.com> wrote:
"Allen Yao" <yaozhen@ustc.edu> wrote
(1) Is template template parameter supported?
They aren't.
(2) In your opinion, is it just *possible* to support complex non-type template parameters suppose no matter how ugly the user interface will be?
It all depends on:
1) whether it is possible to represent this as a number of compile-time integers, and 2) whether it's possible to return this as a result of a meta-function.
As far as my knowledge of the current state of template meta-programming goes, I don't see how it's possible. OTOH, 3 months ago I thought integral template parameters are impossible to support. And now, thanks to Peder, we do have them :).
In addition, I suggest adding a section in the document of the typeof library to mention the problems about complex non-type template parameters, dependendent non-type template parameters and template template parameters, including whether they are supported or not by the current library, and the possibility or main obstacles for supporting them in the future.
Good idea.
Actually there is one more limitation that keeps bothering me. It is related to nested classes, and most unfortunate because of iterators. IOW, we can't just register, e.g., std::vector<T>::const_iterator (as we do with std::vector<T>), and the user always have to register concrete classes, like std::vector<int>::const_iterator, std::vector<short>::const_iterator, etc., separately, as she needs them. This limitation comes from the "non-deduced context", and applies at least to the compliant implementation, but I think the vintage implementation should have the same problem :(
That is correct. Just a thought on the subject: If we take the example with iterator deduction: given a metafunction is_iterator<> there may be a way around this problem: template<typename T> void deduce_iterator(std::vector<T>::iterator it) {...} template<typename T> void deduce_iterator(std::list<T>::iterator it) {...} template<typename T> void deduce_iterator(std::set<T>::iterator it) {...} struct select_deduce_iterator { template<typename T> static void deduce(const T& t) { deduce_iterator<T::value_type>(t); } }; template<typename T> void deduce_fallback(const T& t) { if_<is_iterator<T>, select_deduce_iterator, select_report_error,
::type type; type::deduce(t); }
Problem here of cource is that iterator also needs a difference_type from the container, which it gets from the allocator. It may be possible to construct a dummy allocator type with the correct difference_type just to get the types right. The above method relies on being hardwired into the system, but it should be possible to separate this functionality out by using SFINAE. Regards, Peder
Regards,
Arkadiy
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Peder Holt wrote:
given a metafunction is_iterator<> there may be a way around this problem:
Problem is, it's impossible to write that metafunction. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

On Thu, 02 Dec 2004 08:21:43 -0500, David Abrahams <dave@boost-consulting.com> wrote:
Peder Holt wrote:
given a metafunction is_iterator<> there may be a way around this problem:
Problem is, it's impossible to write that metafunction.
:( What a shame. For dinkumware stl (for VC6.5) it is possible to write a more specialized metafunction: is_stl_iterator<> as the relevant iterators has a common base class (vector<T> uses T*) Is this also feasible for other stl-implementations? Of course, this would only solve the problem for stl containers. The question is whether this is a common enough usage that it is advisable to implement support for it. Peder
-- Dave Abrahams Boost Consulting http://www.boost-consulting.com
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Peder Holt wrote:
given a metafunction is_iterator<> there may be a way around this
"David Abrahams" <dave@boost-consulting.com> wrote problem:
Problem is, it's impossible to write that metafunction.
Well, it's not possible in general case, but for the purpose of typeof, a rough approximation may be enough. We can just assume that, if the type was not caught by all the specializations (generated by registration), then it *might be* one of the standard iterators. We can use SFINAE, examining value_type, distance_type, etc., to increase the probability of that assumption. The value_type then may be extracted, and using it, all the thing may be matched against pre-defined specializations for standard iterators, like: // call traits<It::value_type, It>::.... // specialization template<class T> class traits<T, vector<T>::iterator> { ... }; Now T can be deduced (at least by VC7.1). If our guess was wrong, and this is not a standard iterator after all, it will fail at this stage. The problem with this approach is that, also it's [usually] possible to extract value_type from the iterator, it's not true for allocators, predicates, etc., and so can work only for containers with defaults. Note that the problem is unfortunate mostly because of standard iterators. In general case, iterators can be developed as stand-alone templates, and typedef in the container can be used. These kind of iterators can be just registered as any other template. Arkadiy

Arkadiy Vertleyb wrote:
"David Abrahams" <dave@boost-consulting.com> wrote
Peder Holt wrote:
given a metafunction is_iterator<> there may be a way around this
problem:
Problem is, it's impossible to write that metafunction.
Well, it's not possible in general case, but for the purpose of typeof, a rough approximation may be enough. We can just assume that, if the type was not caught by all the specializations (generated by registration), then it *might be* one of the standard iterators. We can use SFINAE, examining value_type, distance_type, etc., to increase the probability of that assumption.
As long as you don't mind access violations when one of those typedefs happens to be present, but private. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote
Arkadiy Vertleyb wrote:
Well, it's not possible in general case, but for the purpose of typeof, a rough approximation may be enough. We can just assume that, if the type was not caught by all the specializations (generated by registration), then it *might be* one of the standard iterators. We can use SFINAE, examining value_type, distance_type, etc., to increase the probability of that assumption.
As long as you don't mind access violations when one of those typedefs happens to be present, but private.
I didn't think about it, and I didn't realise SFINAE can't handle private typedefs. However recall that this applies only to types not registered in a normal way. So, for these types only, we would get an error: can't access private typedef Foo::value_type instead of encode_type is not defined for the type Foo Not very nice, but arguably not an unreasonable price to pay for the ability to register standard iterators on the typeof library level... Unfortunately the problem doesn't seem to get solved anyway... Arkadiy

On Thu, 2 Dec 2004 11:28:44 -0500, Arkadiy Vertleyb <vertleyb@hotmail.com> wrote:
"David Abrahams" <dave@boost-consulting.com> wrote
Arkadiy Vertleyb wrote:
Well, it's not possible in general case, but for the purpose of typeof, a rough approximation may be enough. We can just assume that, if the type was not caught by all the specializations (generated by registration), then it *might be* one of the standard iterators. We can use SFINAE, examining value_type, distance_type, etc., to increase the probability of that assumption.
As long as you don't mind access violations when one of those typedefs happens to be present, but private.
I didn't think about it, and I didn't realise SFINAE can't handle private typedefs.
However recall that this applies only to types not registered in a normal way. So, for these types only, we would get an error:
can't access private typedef Foo::value_type
instead of
encode_type is not defined for the type Foo
Not very nice, but arguably not an unreasonable price to pay for the ability to register standard iterators on the typeof library level...
Unfortunately the problem doesn't seem to get solved anyway...
Arkadiy
It may be that we will need separate implementation for the different STL-implementations. I have looked at the stl-implementations of VC6.5, VC7.1,GCC 3.2 and STLport 4.5.3.
From what I have seen so far, the only real problem are the implementations that define the iterator class inside the container, such as dinkumware. GCC 3.2 and STLport typedefs global iterator types. In this case, we need only register these iterator types.
The iterators in dinkumware luckily have a common base class: std::iterator<> We can exploit this in order to make an implementation of is_stl_iterator<> When it comes to the allocator type, it is used only in generating template arguments to the iterator class. Here we can create a dummy allocator type that defines the correct typedefs, and we have solved the problem. But I agree, it seems impossible to create one unified solution to the problem. Peder
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

"Peder Holt" <peder.holt@gmail.com> wrote
From what I have seen so far, the only real problem are the implementations that define the iterator class inside the container, such as dinkumware.
Correct. It is just happens to be used by MSVC...
GCC 3.2
which is used for testing only, since it supports typeof natively...
and STLport typedefs global iterator types. In this case, we need only register these iterator types.
Correct.
The iterators in dinkumware luckily have a common base class: std::iterator<> We can exploit this in order to make an implementation of is_stl_iterator<> When it comes to the allocator type, it is used only in generating template arguments to the iterator class. Here we can create a dummy allocator type that defines the correct typedefs, and we have solved the problem.
But I agree, it seems impossible to create one unified solution to the
Can you ellaborate on the "dummy allocator" idea -- I am not sure I understand it. problem. Correct, even if all the STLs in the world used global iterator templates, they would use different ones, since it's not in the standard :-( Arkadiy

On Thu, 2 Dec 2004 16:54:15 -0500, Arkadiy Vertleyb <vertleyb@hotmail.com> wrote:
"Peder Holt" <peder.holt@gmail.com> wrote
From what I have seen so far, the only real problem are the implementations that define the iterator class inside the container, such as dinkumware.
Correct. It is just happens to be used by MSVC...
GCC 3.2
which is used for testing only, since it supports typeof natively...
and STLport typedefs global iterator types. In this case, we need only register these iterator types.
Correct.
The iterators in dinkumware luckily have a common base class: std::iterator<> We can exploit this in order to make an implementation of is_stl_iterator<> When it comes to the allocator type, it is used only in generating template arguments to the iterator class. Here we can create a dummy allocator type that defines the correct typedefs, and we have solved the problem.
Can you ellaborate on the "dummy allocator" idea -- I am not sure I understand it.
Forget it :( I was missing a major point. Using a dummy allocator will only help deduce the iterators base class. Since the iterator class itself is defined inside the container, it will be dependent on all the template arguments of the container. My suggestion will only solve the problem for default arguments of the allocator and predicative, and not at all for maps. It is of cource possible to allow the user to register allocators, and thereby creating template specializations that will cover these, but the problem with predicatives and keys for maps still remain.
But I agree, it seems impossible to create one unified solution to the problem.
Correct, even if all the STLs in the world used global iterator templates, they would use different ones, since it's not in the standard :-(
Arkadiy
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

... Turns out that the problem can be solved rather elegantly (for VC6.5, anyway :) The following code compiles in VC 6.5 : #pragma warning (disable:4786) #include <map> #include <list> template<typename A0,typename A1> void deduce_container(std::list<A0,A1>::iterator) { int b=0; } template<typename A0,typename A1,typename A2,typename A3,typename A4> void deduce_container(std::_Tree<A0, A1, A2, A3, A4>::iterator) { int b=0; } void main() { std::map<int,double>::iterator a; std::list<int*>::iterator b; deduce_container(a); deduce_container(b); } (Note that std::set<A0,A1,A2>::iterator is a typedef, and can not be deduced. std::_Tree<...>::iterator is an nested class, and can be deduced) I don't know if this is legal for other compilers, but if it is, we should define a new macro: REGISTER_NESTED_TEMPLATE_CLASS(std::list,2,iterator) It would then be possible to solve the stl problem outside the typeof library, in e.g. the stl/register.hpp (With separate registrations for the different stl-implementations, of course) Peder

On Tue, 7 Dec 2004 08:35:16 +0100, Peder Holt <peder.holt@gmail.com> wrote:
... Turns out that the problem can be solved rather elegantly (for VC6.5, anyway :) The following code compiles in VC 6.5 :
#pragma warning (disable:4786) #include <map> #include <list>
template<typename A0,typename A1> void deduce_container(std::list<A0,A1>::iterator) { int b=0; }
template<typename A0,typename A1,typename A2,typename A3,typename A4> void deduce_container(std::_Tree<A0, A1, A2, A3, A4>::iterator) { int b=0; }
void main() { std::map<int,double>::iterator a; std::list<int*>::iterator b; deduce_container(a); deduce_container(b); } (Note that std::set<A0,A1,A2>::iterator is a typedef, and can not be deduced. std::_Tree<...>::iterator is an nested class, and can be deduced)
I don't know if this is legal for other compilers, but if it is, we should define a new macro: REGISTER_NESTED_TEMPLATE_CLASS(std::list,2,iterator)
It would then be possible to solve the stl problem outside the typeof library, in e.g. the stl/register.hpp (With separate registrations for the different stl-implementations, of course)
Peder
... But this is nothing more than what you describe as a "non-deduced context" :( Can't be applied in the general case, but solves the stl iterators problem for selected compilers. Of course, if this doesn't compile with VC7.1, it is of no use anyway. Peder

On 12/07/2004 05:54 AM, Peder Holt wrote:
On Tue, 7 Dec 2004 08:35:16 +0100, Peder Holt <peder.holt@gmail.com> wrote: [snip] ... But this is nothing more than what you describe as a "non-deduced context" :( Can't be applied in the general case, but solves the stl iterators problem for selected compilers. Of course, if this doesn't compile with VC7.1, it is of no use anyway.
Peder, There's a workaround to non-deduced context, but using it requires specializations for each instantiation of the outer class. At least I think it works. I've used it with intel's compiler and it seems to work. A discussion of the workaround and a possible solution in a minor change to the language is discussed in: http://groups-beta.google.com/group/comp.std.c++/messages/ea2f9ccdabee9122,dd7fdb68f434be6d,013f08dccd789c33,fbf4388c37565c90,f406ed639436ca30?thread_id=ffee35abd2c61850&mode=thread&noheader=1#doc_f406ed639436ca30 HTH. Regards, Larry

"Larry Evans" <cppljevans@cox-internet.com> wrote
There's a workaround to non-deduced context, but using it requires specializations for each instantiation of the outer class.
Can't we then just register concrete iterators? BOOST_TYPEOF_REGISTER_TYPE(std::vector<int>::iterator); BOOST_TYPEOF_REGISTER_TYPE(std::map<int, std::string>::iterator); etc. Arkadiy

On 12/07/2004 09:53 AM, Arkadiy Vertleyb wrote:
"Larry Evans" <cppljevans@cox-internet.com> wrote
There's a workaround to non-deduced context, but using it requires specializations for each instantiation of the outer class.
Can't we then just register concrete iterators?
BOOST_TYPEOF_REGISTER_TYPE(std::vector<int>::iterator); BOOST_TYPEOF_REGISTER_TYPE(std::map<int, std::string>::iterator); etc.
OOPS. I guess you're right. I guess I was thinking that since it was some help in my problem (policy ptrs), then it would naturally extend to other cases. However, in my problem, there would be relatively few specializations; hence, I guess it was worthwhile. In the typeof case, I guess not. I'm still wondering whether the :0: token proposed in the mentioned post to c.s.c++ would solve the problem.

"Peder Holt" <peder.holt@gmail.com> wrote in message
... But this is nothing more than what you describe as a "non-deduced context" :( Can't be applied in the general case, but solves the stl iterators problem for selected compilers. Of course, if this doesn't compile with VC7.1, it is of no use anyway.
Right... I am very much surprised it works on VC6... Arkadiy

On Tue, 7 Dec 2004 11:45:47 -0500, Arkadiy Vertleyb <vertleyb@hotmail.com> wrote:
"Peder Holt" <peder.holt@gmail.com> wrote in message
... But this is nothing more than what you describe as a "non-deduced context" :( Can't be applied in the general case, but solves the stl iterators problem for selected compilers. Of course, if this doesn't compile with VC7.1, it is of no use anyway.
Right... I am very much surprised it works on VC6...
... Then again, the following compiles with VC7.1, so maybe there is hope after all :) #pragma warning (disable:4786) #include <map> #include <list> #include <iostream> template<typename A0,typename A1> void deduce_container(class std::list<A0,A1>::iterator) { std::cout << "list" << "\n"; } template<typename A0> void deduce_container(class std::_Tree<A0>::iterator) { std::cout << "map" << "\n"; } int main() { std::map<int,double>::iterator a; std::list<int*>::iterator b; deduce_container(a); deduce_container(b); return 0; }
Arkadiy
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

"Peder Holt" <peder.holt@gmail.com> wrote
Then again, the following compiles with VC7.1, so maybe there is hope after all :)
Wow... The reason it compiles is that you are using "class" where I used "typename". The following does not work: template<typename A0> void deduce_container(*typename* std::_Tree<A0>::iterator) { std::cout << "map" << "\n"; } I don't think this is a legal standard usage, though... Probably a Microsoft - specific "feature"... Any comments from language experts? Should the following work according to the Standard?
#pragma warning (disable:4786) #include <map> #include <list> #include <iostream>
template<typename A0,typename A1> void deduce_container(class std::list<A0,A1>::iterator) { std::cout << "list" << "\n"; }
template<typename A0> void deduce_container(class std::_Tree<A0>::iterator) { std::cout << "map" << "\n"; }
int main() { std::map<int,double>::iterator a; std::list<int*>::iterator b; deduce_container(a); deduce_container(b); return 0; }
Arkadiy

On Wed, 8 Dec 2004 16:15:47 -0500, Arkadiy Vertleyb <vertleyb@hotmail.com> wrote:
"Peder Holt" <peder.holt@gmail.com> wrote
Then again, the following compiles with VC7.1, so maybe there is hope after all :)
Wow...
The reason it compiles is that you are using "class" where I used "typename". The following does not work:
Correct. I first tried with typename.
template<typename A0> void deduce_container(*typename* std::_Tree<A0>::iterator) { std::cout << "map" << "\n"; }
I don't think this is a legal standard usage, though... Probably a Microsoft - specific "feature"... Any comments from language experts? Should the following work according to the Standard?
I tried a modified version with comeau online compiler, and it did not compile. I like the syntax, though. There is a difference between nested classes and typedefs, and this is a nice way to show the difference explicitly in the source :) I have written a simple test in order to discover if other compilers support it: template<typename T> struct outer { class nested{}; }; template<typename T> void deduce(class outer<T>::nested) {} int main() { outer<int>::nested a; deduce(a); return 0; } Successfully compiles on VC6.5 and VC7.1 Fails to compile on Comeau C/C++ 4.3.3 I propose to define the macro BOOST_HAS_TEMPLATE_NESTED_CLASS_DEDUCTION for the VC compilers (and possibly other compilers supporting this) and supplying BOOST_TYPEOF_REGISTER_TEMPLATE_NESTED if the above is set. Peder
#pragma warning (disable:4786) #include <map> #include <list> #include <iostream>
template<typename A0,typename A1> void deduce_container(class std::list<A0,A1>::iterator) { std::cout << "list" << "\n"; }
template<typename A0> void deduce_container(class std::_Tree<A0>::iterator) { std::cout << "map" << "\n"; }
int main() { std::map<int,double>::iterator a; std::list<int*>::iterator b; deduce_container(a); deduce_container(b); return 0; }
Arkadiy
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On 12/09/2004 12:25 AM, Peder Holt wrote: [sni]
I propose to define the macro BOOST_HAS_TEMPLATE_NESTED_CLASS_DEDUCTION for the VC compilers (and possibly other compilers supporting this) and supplying BOOST_TYPEOF_REGISTER_TEMPLATE_NESTED if the above is set.
Wouldn't this just encourage the writting of code not conforming to the c++ standard?

On Thu, 09 Dec 2004 06:44:00 -0700, Larry Evans <cppljevans@cox-internet.com> wrote:
On 12/09/2004 12:25 AM, Peder Holt wrote: [sni]
I propose to define the macro BOOST_HAS_TEMPLATE_NESTED_CLASS_DEDUCTION for the VC compilers (and possibly other compilers supporting this) and supplying BOOST_TYPEOF_REGISTER_TEMPLATE_NESTED if the above is set.
Wouldn't this just encourage the writting of code not conforming to the c++ standard?
Hmm. You have a point. The main reason for creating something like this would be to allow registration of the dinkumware iterators, which are defined as nested classes (unlike the iterators of other stl-implementations which are normal template classes already supported by the TYPEOF library) BOOST_TYPEOF_REGISTER_TEMPLATE_NESTED should only be used in this context, and not promoted outside of the TYPEOF library. This functionality could also be implemented in the same scope as the stl registration code. This would prevent the TYPEOF library from being polluted, but would allow automatic registration of iterators for all platforms. Peder
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

"Peder Holt" <peder.holt@gmail.com> wrote
The main reason for creating something like this would be to allow registration of the dinkumware iterators, which are defined as nested classes (unlike the iterators of other stl-implementations which are normal template classes already supported by the TYPEOF library) BOOST_TYPEOF_REGISTER_TEMPLATE_NESTED should only be used in this context, and not promoted outside of the TYPEOF library.
This functionality could also be implemented in the same scope as the stl registration code. This would prevent the TYPEOF library from being polluted, but would allow automatic registration of iterators for all platforms.
Actually this method is only good with overloading -- doesn't work with partial template specialization. So, for the conformant implementation, we would have to implement some additional mechanism in the main template... So I am not sure we would be really able to "prevent the TYPEOF library from being polluted". Arkadiy

On Thu, 9 Dec 2004 10:05:24 -0500, Arkadiy Vertleyb <vertleyb@hotmail.com> wrote:
"Peder Holt" <peder.holt@gmail.com> wrote
The main reason for creating something like this would be to allow registration of the dinkumware iterators, which are defined as nested classes (unlike the iterators of other stl-implementations which are normal template classes already supported by the TYPEOF library) BOOST_TYPEOF_REGISTER_TEMPLATE_NESTED should only be used in this context, and not promoted outside of the TYPEOF library.
This functionality could also be implemented in the same scope as the stl registration code. This would prevent the TYPEOF library from being polluted, but would allow automatic registration of iterators for all platforms.
Actually this method is only good with overloading -- doesn't work with partial template specialization. So, for the conformant implementation, we would have to implement some additional mechanism in the main template...
So I am not sure we would be really able to "prevent the TYPEOF library from being polluted".
Hmm. This is starting to look really ugly. I'll have one more go before abandoning this. We cannot place support for template nested class deduction directly into the typeof library: 1. It would break the elegance of the source 2. It exploits a compiler bug 3. It is only applicable for a single compiler series. I think I have found a way to separate the code from the library, given the restrictions above. Assuming that all the source will be placed in a compiler/stl-implementation specific folder: boost/typeof/stl/dinkumware_vc/ 1. Define the generic version of encode_type_impl (So far it has only been forward declared. 2. Create a template function encode_type_fn. 3. Use encode_type_fn to forward type deduction from encode_type_impl (Default implementation causes compile time failure with the proper error messages) 4. Overload encode_type_fn for each of the nested classes. The problem with this approach, is obviously that a function can only represent a single integral value at compile time, while we need a vector of them. The only way I know of to transfer a vector of integral values compile time across a function, is to use the compile time constants vector. Well, I guess it is back to square one. At least we tried. Peder
Arkadiy
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On 12/10/2004 01:58 AM, Larry Evans wrote:
On 12/10/2004 12:32 AM, Peder Holt wrote: [snip]
Well, I guess it is back to square one. At least we tried.
Propose a change in the standard on comp.std.c++ and see what feedback you get.
Peder, it just occurred to me that instead of the proposed change of adding :0: as done in: http://groups-beta.google.com/group/comp.std.c++/messages/ea2f9ccdabee9122,dd7fdb68f434be6d,013f08dccd789c33,fbf4388c37565c90,f406ed639436ca30?thread_id=ffee35abd2c61850&mode=thread&noheader=1#doc_f406ed639436ca30 I'm supposing that if A<T>::B, which current means T is in a non-deduced context, were changed to mean A<T>:0:B as in the above proposal, then everything would work, AFAICT. IOW, no change is needed in the syntax, only change is needed in the meaning of non-deduced contexts. Instead of non-deduced context, rename to nested context. In other words: A<T>::B would mean B is nested in the "immediate" A<T> class and not in any superclass of A<T>. This would avoid the problem cited in: http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&selm=uvflpetzg.fsf%40boost-consulting.com Does this seem like it would work?

On Fri, 10 Dec 2004 03:09:23 -0700, Larry Evans <cppljevans@cox-internet.com> wrote:
On 12/10/2004 01:58 AM, Larry Evans wrote:
On 12/10/2004 12:32 AM, Peder Holt wrote: [snip]
Well, I guess it is back to square one. At least we tried.
Propose a change in the standard on comp.std.c++ and see what feedback you get.
Peder, it just occurred to me that instead of the proposed change of adding :0: as done in:
I'm supposing that if A<T>::B, which current means T is in a non-deduced context, were changed to mean A<T>:0:B as in the above proposal, then everything would work, AFAICT. IOW, no change is needed in the syntax, only change is needed in the meaning of non-deduced contexts. Instead of non-deduced context, rename to nested context. In other words:
A<T>::B
would mean B is nested in the "immediate" A<T> class and not in any superclass of A<T>. This would avoid the problem cited in:
http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&selm=uvflpetzg.fsf%40boost-consulting.com
Does this seem like it would work?
Probably, but it still won't work with existing compilers. The typeof library was created in order to support typeof until the time that this is included in the standard. Compiler support for typeof will probably be available before the definition of non-deduced-context is changed. Apart from that, I support your proposal. Peder
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On 12/10/2004 03:00 AM, Peder Holt wrote: [snip]
would mean B is nested in the "immediate" A<T> class and not in any superclass of A<T>. This would avoid the problem cited in:
http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&selm=uvflpetzg.fsf%40boost-consulting.com
Does this seem like it would work?
Probably, but it still won't work with existing compilers. The typeof library was created in order to support typeof until the time that this is included in the standard. Compiler support for typeof will probably be available before the definition of non-deduced-context is changed. Makes sense.
Apart from that, I support your proposal. Except that the further reading convinces me that :0: is better because it wouldn't break existing code and it would have to mean the right operand could'nt refer to a typedef either, in order to avoid the problem illustrated by Sharoni's post.

On 12/10/2004 03:09 AM, Larry Evans wrote: [snip]
Does this seem like it would work?
OOPS. Looking a little further found: http://groups-beta.google.com/group/comp.lang.c++.moderated/messages/9c5e6246d3692d0b,21e80ea0a448980f,5c284ab281122340,aecdeff994a3ab23,b96640f2c4b1082a,9248e91f9a4a0537,84b594817eabf9b7?thread_id=7d5c262634d45137&mode=thread&noheader=1#doc_21e80ea0a448980f where the problem with typedef's is mentioned as the show-stopper.

On Fri, 10 Dec 2004 03:50:58 -0700, Larry Evans <cppljevans@cox-internet.com> wrote:
On 12/10/2004 03:25 AM, Larry Evans wrote:
where the problem with typedef's is mentioned as the show-stopper.
Actually, Rani Sharoni's post in that thread is the best explanation I've seen to date.
Still, the problem in his post applies to typedefs. If A<T>::B is a nested class or struct under A<T>, and not a typedef, deduction should always be possible. In the case where B is a typedef: typedef typename some_class<T> B; you can deduce some_class<T> instead of A<T>::B Peder
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On 12/10/2004 03:19 AM, Peder Holt wrote: [snip]
Still, the problem in his post applies to typedefs. If A<T>::B is a nested class or struct under A<T>, and not a typedef, deduction should always be possible. Yes. Our posts crossed. I had same idea.
In the case where B is a typedef: typedef typename some_class<T> B; you can deduce some_class<T> instead of A<T>::B
Do you mean in the case of Roni's example, that you can deduce by substitution, i.e. can_deduce: select<B, int, int *>::type --substitute--> can_deduce: select<(C1<T>::value != C2<T>::value), int, int *>::type ?

On Fri, 10 Dec 2004 04:49:41 -0700, Larry Evans <cppljevans@cox-internet.com> wrote:
On 12/10/2004 03:19 AM, Peder Holt wrote: [snip]
Still, the problem in his post applies to typedefs. If A<T>::B is a nested class or struct under A<T>, and not a typedef, deduction should always be possible. Yes. Our posts crossed. I had same idea.
In the case where B is a typedef: typedef typename some_class<T> B; you can deduce some_class<T> instead of A<T>::B
Do you mean in the case of Roni's example, that you can deduce by substitution, i.e.
can_deduce: select<B, int, int *>::type --substitute--> can_deduce: select<(C1<T>::value != C2<T>::value), int, int *>::type
?
Nope. can_deduce<T>::type is either int or int*, so we need to make specializations for int and int*, and can ignore can_deduce<T> altogether. Type deduction of nested typedefs would as far as I can see require that can_deduce<T>::type be a separate type from int and int*.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Peder Holt wrote:
On Fri, 10 Dec 2004 03:50:58 -0700, Larry Evans <cppljevans@cox-internet.com> wrote:
On 12/10/2004 03:25 AM, Larry Evans wrote:
where the problem with typedef's is mentioned as the show-stopper.
Actually, Rani Sharoni's post in that thread is the best explanation I've seen to date.
Still, the problem in his post applies to typedefs. If A<T>::B is a nested class or struct under A<T>, and not a typedef, deduction should always be possible.
In the case where B is a typedef: typedef typename some_class<T> B; you can deduce some_class<T> instead of A<T>::B
No, you can't. Given some_class<V> as input to the pattern A<T>::B, you have no way to deduce T. template<class T> struct A { typedef typename arbitrarily_complex_metafunction<T>::type B; }; And of course getting back to iterators, you have no way of determining whether T* is T*, vector<T, A>::iterator, or basic_string<T, Tr, A>::iterator, much less deducing A or Tr.

On Fri, 10 Dec 2004 14:54:26 +0200, Peter Dimov <pdimov@mmltd.net> wrote:
Peder Holt wrote:
On Fri, 10 Dec 2004 03:50:58 -0700, Larry Evans <cppljevans@cox-internet.com> wrote:
On 12/10/2004 03:25 AM, Larry Evans wrote:
where the problem with typedef's is mentioned as the show-stopper.
Actually, Rani Sharoni's post in that thread is the best explanation I've seen to date.
Still, the problem in his post applies to typedefs. If A<T>::B is a nested class or struct under A<T>, and not a typedef, deduction should always be possible.
In the case where B is a typedef: typedef typename some_class<T> B; you can deduce some_class<T> instead of A<T>::B
No, you can't. Given some_class<V> as input to the pattern A<T>::B, you have no way to deduce T.
template<class T> struct A { typedef typename arbitrarily_complex_metafunction<T>::type B; };
And of course getting back to iterators, you have no way of determining whether T* is T*, vector<T, A>::iterator, or basic_string<T, Tr, A>::iterator, much less deducing A or Tr.
What I was trying to say, was that, given that there are no nested classes involved, arbitrarily_complex_metafunction<T>::type will in the end be reduced to arbitrary_complex_type<A0,A1,A2,...>, which is a concrete type which can be deduced. For the typeof library this is sufficient. On the other hand: template<class T> struct A { class B; }; A<T>::B now should give sufficient information to be deduced.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

"Peder Holt" <peder.holt@gmail.com> wrote
What I was trying to say, was that, given that there are no nested classes involved, arbitrarily_complex_metafunction<T>::type will in the end be reduced to arbitrary_complex_type<A0,A1,A2,...>, which is a concrete type which can be deduced. For the typeof library this is sufficient.
On the other hand: template<class T> struct A { class B; }; A<T>::B now should give sufficient information to be deduced.
Please note that, as Peder has mentioned, the language support for typeof is probably going to be in the Standard before any other changes. Therefore, even if the changes related to the non-deduced context may be a valuable addition to the Standard, I don't think this is relevant to the typeof library -- we have to live with what we have... Arkadiy
participants (6)
-
Allen Yao
-
Arkadiy Vertleyb
-
David Abrahams
-
Larry Evans
-
Peder Holt
-
Peter Dimov