
I could use one to enable a range constructor only where appropriate: class X { template<typename range_t> X (range_t const&, enable_if<is_range<range_t> >::type *dummy=0) Question is, what might 'is_range' look like?

I guess it has to possess a ::value static boolean... Regarding the code that determines whether the parameter is a range or not, hmm it's like you can/want. On 10/3/08, Neal Becker <ndbecker2@gmail.com> wrote:
I could use one to enable a range constructor only where appropriate:
class X { template<typename range_t> X (range_t const&, enable_if<is_range<range_t> >::type *dummy=0)
Question is, what might 'is_range' look like?
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
-- Alp Mestan --- http://blog.mestan.fr/ --- http://alp.developpez.com/ --- In charge of the Qt, Algorithms and Artificial Intelligence sections on Developpez

Alp Mestan wrote:
I guess it has to possess a ::value static boolean... Regarding the code that determines whether the parameter is a range or not, hmm it's like you can/want.
On 10/3/08, Neal Becker <ndbecker2@gmail.com> wrote:
I could use one to enable a range constructor only where appropriate:
class X { template<typename range_t> X (range_t const&, enable_if<is_range<range_t> >::type *dummy=0)
Question is, what might 'is_range' look like?
_______________________________________________
I noticed that range has a <range/concepts.hpp>. I wonder if I could use e.g., SinglePassRangeConcept? I don't know if this could be used to provide an enable_if type functionality (or how to do it).

Neal Becker wrote:
I noticed that range has a <range/concepts.hpp>. I wonder if I could use e.g., SinglePassRangeConcept? I don't know if this could be used to provide an enable_if type functionality (or how to do it).
This concept checking isn't really done at compile-time, so you cannot use its result with SFINAE. That's one of the major drawbacks of the concept checking library.

AMDG Mathias Gaunard wrote:
This concept checking isn't really done at compile-time, so you cannot use its result with SFINAE. That's one of the major drawbacks of the concept checking library.
It is done at compile time. It just gives a compiles/doesn't compile answer rather than a boolean result that can be tested. In Christ, Steven Watanabe

On Fri, Oct 3, 2008 at 5:59 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
Mathias Gaunard wrote:
This concept checking isn't really done at compile-time, so you cannot use its result with SFINAE. That's one of the major drawbacks of the concept checking library.
It is done at compile time. It just gives a compiles/doesn't compile answer rather than a boolean result that can be tested.
Is there any other option? I mean if t<x> is ill-formed, because the type x doesn't support some expression used in the template t, then is there some context where t could be instantiated with x without making the whole program ill-formed? I can't think of one. If there were such a context, then you might be able associate t<x>'s ill-formation with some boolean constant, and you would have a way to implement tests based on concept checking templates - a sort of concept-based type introspection for C++03, which would be way cool. However, without such a context, the best you can do is fail gracefully with informative compilation errors, which is the purpose of the concept checking library. This brings up an interesting question regarding the proposed concept language extensions for C++0x: If a function in an overload set requires a concept that its argument doesn't model but some other function in the set accepts the argument, does overload resolution succeed? In other words, does the proposal support Concept Requirement Failure Is Not An Error? CRFINAE. ;-) Daniel Walker

The answer is yes. Sent from my iPhone On Oct 5, 2008, at 6:06 PM, "Daniel Walker" <daniel.j.walker@gmail.com> wrote:
On Fri, Oct 3, 2008 at 5:59 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
Mathias Gaunard wrote:
This concept checking isn't really done at compile-time, so you cannot use its result with SFINAE. That's one of the major drawbacks of the concept checking library.
It is done at compile time. It just gives a compiles/doesn't compile answer rather than a boolean result that can be tested.
Is there any other option? I mean if t<x> is ill-formed, because the type x doesn't support some expression used in the template t, then is there some context where t could be instantiated with x without making the whole program ill-formed? I can't think of one.
If there were such a context, then you might be able associate t<x>'s ill-formation with some boolean constant, and you would have a way to implement tests based on concept checking templates - a sort of concept-based type introspection for C++03, which would be way cool. However, without such a context, the best you can do is fail gracefully with informative compilation errors, which is the purpose of the concept checking library.
This brings up an interesting question regarding the proposed concept language extensions for C++0x: If a function in an overload set requires a concept that its argument doesn't model but some other function in the set accepts the argument, does overload resolution succeed? In other words, does the proposal support Concept Requirement Failure Is Not An Error? CRFINAE. ;-)
Daniel Walker _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Sun, Oct 5, 2008 at 6:47 PM, David Abrahams <dave@boostpro.com> wrote:
The answer is yes.
Yes to CRFINAE? That's cool! So, we could use that for concept-based introspection... maybe it's already possible to write is_range for ConceptGCC. Is anyone working on this sort of thing? Daniel

on Sun Oct 05 2008, "Daniel Walker" <daniel.j.walker-AT-gmail.com> wrote:
On Sun, Oct 5, 2008 at 6:47 PM, David Abrahams <dave@boostpro.com> wrote:
The answer is yes.
Yes to CRFINAE? That's cool!
Of course; without it concept-based overload resolution would be pretty useless.
So, we could use that for concept-based introspection...
Yes, concepts can do most introspection jobs.
maybe it's already possible to write is_range for ConceptGCC.
I don't know what properties you want to test for, but concepts can handle the syntactic part. However, in C++0x you'd probably not use is_range but instead use "requires Range<R>"
Is anyone working on this sort of thing?
What sort? -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Sun, Oct 5, 2008 at 9:39 PM, David Abrahams <dave@boostpro.com> wrote:
maybe it's already possible to write is_range for ConceptGCC.
I don't know what properties you want to test for, but concepts can handle the syntactic part. However, in C++0x you'd probably not use is_range but instead use "requires Range<R>"
Yeah, "requires Range<R>" for dispatching functions, etc., and is_range for metaprogramming.
Is anyone working on this sort of thing?
What sort?
Concept-based type introspection. Or metaprogramming with concepts. The Concept Traits Library that Mathias linked to is aiming in the right direction. Daniel

Daniel Walker wrote:
Is there any other option? I mean if t<x> is ill-formed, because the type x doesn't support some expression used in the template t, then is there some context where t could be instantiated with x without making the whole program ill-formed? I can't think of one.
SFINAE for expressions, available in C++0x (GCC 4.4 implements it, albeit only with sizeof and not with decltype).
If there were such a context, then you might be able associate t<x>'s ill-formation with some boolean constant, and you would have a way to implement tests based on concept checking templates - a sort of concept-based type introspection for C++03, which would be way cool.
That thing is mostly already doable in C++03. See this, for example: <http://neoscientists.org/~tschwinger/boostdev/concept_traits/libs/concept_traits/doc/>
This brings up an interesting question regarding the proposed concept language extensions for C++0x: If a function in an overload set requires a concept that its argument doesn't model but some other function in the set accepts the argument, does overload resolution succeed?
Of course.

On Sun, Oct 5, 2008 at 7:54 PM, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
Daniel Walker wrote:
Is there any other option? I mean if t<x> is ill-formed, because the type x doesn't support some expression used in the template t, then is there some context where t could be instantiated with x without making the whole program ill-formed? I can't think of one.
SFINAE for expressions, available in C++0x (GCC 4.4 implements it, albeit only with sizeof and not with decltype).
That's great news! That would do the trick!
If there were such a context, then you might be able associate t<x>'s ill-formation with some boolean constant, and you would have a way to implement tests based on concept checking templates - a sort of concept-based type introspection for C++03, which would be way cool.
That thing is mostly already doable in C++03. See this, for example: <http://neoscientists.org/~tschwinger/boostdev/concept_traits/libs/concept_traits/doc/>
This is the first I've heard of this project, but from skimming the documentation, I gather this library is not actually testing for concepts (as in restraints on expressions), but instead it is testing for class members. So, this approach couldn't cover concepts from the BGL or Boost.Range or even the standard library's Swappable, because none of these concepts are defined in terms of class members. They're defined in terms expressions: begin(range) rather than range.begin(), swap(x, y) rather than x.swap(y). Thus, to test for concepts you need to be able to recover from ill-formed expressions... if expression SFINAE with sizeof() actually works, that could have big implications... a compile-time eval? You could write is_compilable()! ;-)
This brings up an interesting question regarding the proposed concept language extensions for C++0x: If a function in an overload set requires a concept that its argument doesn't model but some other function in the set accepts the argument, does overload resolution succeed?
Of course.
Yes, I'm also glad to hear this. Do you know if this is supported in ConceptGCC already? It's not clear to me from the documentation. Actually, I should just download it and play around. Thanks! Daniel Walker

Daniel Walker wrote:
That's great news! That would do the trick!
Indeed, it's pretty cool. In C++0x, if you write template<typename T> auto foo(T&& t) -> decltype(t.foo()) { return t.foo(); } Then that definition is only visible if T has a nullary foo member function. It's basically the same as type inference in functional programming. As of today, in GCC 4.4, you can do something equivalent but have to be significantly more verbose: template<typename T, size_t Cond> struct foo_type { typedef decltype(((T*)0)->foo()) type; }; template<typename T> typename foo_type<T, sizeof(((T*)0)->foo() > 0)>::type foo(T&& t) { return t.foo(); } (You cannot put decltype directly in the return type because of name mangling issues)

Mathias Gaunard a écrit :
As of today, in GCC 4.4, you can do something equivalent but have to be significantly more verbose:
template<typename T, size_t Cond> struct foo_type { typedef decltype(((T*)0)->foo()) type; };
template<typename T> typename foo_type<T, sizeof(((T*)0)->foo() > 0)>::type foo(T&& t) { return t.foo(); }
(You cannot put decltype directly in the return type because of name mangling issues)
Can't this be packaged into some macro like BOOST_HAS_XXX ?

On Mon, Oct 6, 2008 at 7:02 AM, Joel Falcou <joel.falcou@u-psud.fr> wrote:
Mathias Gaunard a écrit :
As of today, in GCC 4.4, you can do something equivalent but have to be significantly more verbose:
template<typename T, size_t Cond> struct foo_type { typedef decltype(((T*)0)->foo()) type; };
template<typename T> typename foo_type<T, sizeof(((T*)0)->foo() > 0)>::type foo(T&& t) { return t.foo(); }
(You cannot put decltype directly in the return type because of name mangling issues)
Can't this be packaged into some macro like BOOST_HAS_XXX ?
Yeah, that's kind of what I was getting at by a compile time eval or is_compilable. But those are misnomers. You're not checking validity for whole blocks or statements, just single expressions with a given type. But yeah, you could wrap the general boilerplate in a preprocessor metafunction and maybe call it something like BOOST_HAS_EXPRESSION. Of course, the expressions I'm interested in would check for a concept, for example, an expression like function_requires<ForwardRange<T> >(). So for a boolean metafunction that checks if a type models some concept, the final C++0x code (for platforms without concept language support) would be something like: template<class ConceptCeck, class T> struct has_concept { typedef char (&yes)[1]; typedef char (&no)[2]; template<typename T> static no test(...); template<typename T> static yes test(T* t) -> decltype(function_requires<ConceptCheck<T> >()); public: static const bool value = sizeof(test<T>(0)) == sizeof(yes); typedef boost::mpl::bool_<value> type; }; BOOST_MPL_ASSERT((has_concept<ForwardRange, vector<int> >)); For platforms with concept language support, you would use CRFINAE instead of expression SFINAE on the two test() functions. At least, this is the general idea. I assume something like this would work... Daniel

Daniel Walker a écrit :
Yeah, that's kind of what I was getting at by a compile time eval or is_compilable. But those are misnomers. You're not checking validity for whole blocks or statements, just single expressions with a given type. But yeah, you could wrap the general boilerplate in a preprocessor metafunction and maybe call it something like BOOST_HAS_EXPRESSION. <snip> For platforms with concept language support, you would use CRFINAE instead of expression SFINAE on the two test() functions. At least, this is the general idea. I assume something like this would work...
I use this kind of code in a large number of code of my own and already have some proper macro. Mayeb i can upload my files somewhere so we can check ?

On Tue, Oct 7, 2008 at 2:52 AM, Joel Falcou <joel.falcou@u-psud.fr> wrote:
Daniel Walker a écrit :
Yeah, that's kind of what I was getting at by a compile time eval or is_compilable. But those are misnomers. You're not checking validity for whole blocks or statements, just single expressions with a given type. But yeah, you could wrap the general boilerplate in a preprocessor metafunction and maybe call it something like BOOST_HAS_EXPRESSION.
<snip>
For platforms with concept language support, you would use CRFINAE instead of expression SFINAE on the two test() functions. At least, this is the general idea. I assume something like this would work...
I use this kind of code in a large number of code of my own and already have some proper macro. Mayeb i can upload my files somewhere so we can check ?
I don't think we exactly understand each other here. Mathias' examples and mine both use C++0x features that, to my knowledge, are not available on any released compiler (gcc 4.4 is in beta). The point in question is the use of C++0x expression SFINAE and CRFINAE to implement concept checking as a boolean metafunction. By BOOST_HAS_EXPRESSION, I mean a general preprocessor boilerplate macro that would generate metafunctions to detect the validity of ANY expression as evaluated in the context of decltype or sizeof, i.e. not just membership access but virtually any non-void expression. I don't believe that's possible on C++03. Of course, I think there is a need to package SFINAE techniques as a nice library for compile-time class-based type introspection - something beyond MPL's HAS_XXX. I've done some work on this myself, actually, and I once submitted a patch implementing HAS_XXX for member templates, but I believe it got lost in the SVN migration. This is another topic that doesn't relate to is_range, but yeah, sure, if you have something along these lines, by all means, share it! ;-) Daniel Walker

Daniel Walker a écrit :
Of course, I think there is a need to package SFINAE techniques as a nice library for compile-time class-based type introspection - something beyond MPL's HAS_XXX. I've done some work on this myself, actually, and I once submitted a patch implementing HAS_XXX for member templates, but I believe it got lost in the SVN migration. This is another topic that doesn't relate to is_range, but yeah, sure, if you have something along these lines, by all means, share it! ;-)
Yeah we kinda miscommunicated on this topic. I'll gather what I have and see what is worth sharing. basically, what I tried to do was a generic BOOST_HAS_METHOD_NAMED(foo, (int,int)) that check for presence of a given method with a given prototypes in types with variations to catch or not to catch const version of a named methods etc. The code is rather simple IIRC as it's roaming the internet since ages but never put into a proper usable macro I think. I also think we can check what's needed for this and how to put it properly. If you think it's worth, maybe we should start a new topic and work over this. -- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

On Tue, Oct 7, 2008 at 3:06 PM, Joel Falcou <joel.falcou@u-psud.fr> wrote:
Daniel Walker a écrit :
Of course, I think there is a need to package SFINAE techniques as a nice library for compile-time class-based type introspection - something beyond MPL's HAS_XXX. I've done some work on this myself, actually, and I once submitted a patch implementing HAS_XXX for member templates, but I believe it got lost in the SVN migration. This is another topic that doesn't relate to is_range, but yeah, sure, if you have something along these lines, by all means, share it! ;-)
Yeah we kinda miscommunicated on this topic. I'll gather what I have and see what is worth sharing. basically, what I tried to do was a generic
BOOST_HAS_METHOD_NAMED(foo, (int,int))
that check for presence of a given method with a given prototypes in types with variations to catch or not to catch const version of a named methods etc. The code is rather simple IIRC as it's roaming the internet since ages but never put into a proper usable macro I think.
That sounds great. Nice that you handle constness. I would suggest adding support for volatility, as well, but yeah, sounds good so far.
I also think we can check what's needed for this and how to put it properly. If you think it's worth, maybe we should start a new topic and work over this.
Sure! If you have member functions, I have member templates, and member types are already in MPL, then all we lack are macros for member data and member function templates. I would suggest naming the complete set of class-based introspection macros like so: BOOST_HAS_MEMBER_DATA BOOST_HAS_MEMBER_TYPE BOOST_HAS_MEMBER_TEMPLATE BOOST_HAS_MEMBER_FUNCTION BOOST_HAS_MEMBER_FUNCTION_TEMPLATE And of course, if expression SFINAE gets ironed out soon, we could go ahead and add BOOST_HAS_EXPRESSION and perhaps some metafunctions in support of concept-based introspection... or maybe a better term for it would be expression introspection. But one step at a time... Why don't we both package what we have, upload to vault, and then work out merging the two and adding the rest in another thread? Daniel Walker

Daniel Walker a écrit :
That sounds great. Nice that you handle constness. I would suggest adding support for volatility, as well, but yeah, sounds good so far.
I'll surely look like some big noobie but ... volatility on methods ?
And of course, if expression SFINAE gets ironed out soon, we could go ahead and add BOOST_HAS_EXPRESSION and perhaps some metafunctions in support of concept-based introspection... or maybe a better term for it would be expression introspection. But one step at a time...
Currently I have*need* to have things like traits telling me if class X supports concept Y but I have not enough expertise on how to handle this but maybe we'll be able to craft this.
Why don't we both package what we have, upload to vault, and then work out merging the two and adding the rest in another thread?
I can't see a 'bestest' plan ;) I'll do my lil' package and upload it during the day. Let's call it introspection_traits or something ;)

On Thu, Oct 9, 2008 at 2:34 AM, Joel Falcou <joel.falcou@u-psud.fr> wrote:
Daniel Walker a écrit :
That sounds great. Nice that you handle constness. I would suggest adding support for volatility, as well, but yeah, sounds good so far.
I'll surely look like some big noobie but ... volatility on methods ?
Member functions can be overloaded on const and volatile - so called cv-qualification. So, it would be good to handle each of the following, for example. struct t { void f(); void f() const; void f() volatile; void f() const volatile; }; I can help after I take a look at your implementation. <snip>
I'll do my lil' package and upload it during the day.
OK, no rush. I won't be able to get to this until this weekend, really. Thanks! Daniel Walker

On Mon, Oct 6, 2008 at 6:58 AM, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
Daniel Walker wrote:
That's great news! That would do the trick!
Indeed, it's pretty cool. In C++0x, if you write
template<typename T> auto foo(T&& t) -> decltype(t.foo()) { return t.foo(); }
Then that definition is only visible if T has a nullary foo member function. It's basically the same as type inference in functional programming.
As of today, in GCC 4.4, you can do something equivalent but have to be significantly more verbose:
So, I tried your suggestion with gcc 4.4, but I got an error. #include <cstddef> template<typename T, size_t Cond> struct foo_type { typedef decltype(((T*)0)->foo()) type; }; template<typename T> typename foo_type<T, sizeof(((T*)0)->foo() > 0)>::type foo(T&& t) { return t.foo(); } struct t0 { int foo() { return 0; } }; int main() { t0 x; foo(x); // error: no matching function for call to 'foo(t0&)' } If I take away the && in foo(), I get ICE. Any idea what's wrong here? Daniel

Daniel Walker wrote:
So, I tried your suggestion with gcc 4.4, but I got an error.
Well, to be honest I didn't test it fully. If you call it with a type that doesn't have a foo member function, the overload is indeed masked. I don't know why it doesn't work when using &&, must be a bug. Of course, the fact that it produces ICE shows it's a bug in itself. I don't really know what really works and what doesn't atm. The first example of this link, however, seems to work: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2634.html I am fairly disappointed to see it actually doesn't work :(. Hopefully it will be fixed before the 4.4 release.

On Tue, Oct 7, 2008 at 2:30 PM, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
Daniel Walker wrote:
So, I tried your suggestion with gcc 4.4, but I got an error.
Well, to be honest I didn't test it fully. If you call it with a type that doesn't have a foo member function, the overload is indeed masked.
Well, it looks like it's also masked when you call it with a type that has a foo member function. The error was "no matching function." So, yeah, this is still a little buggy; it's over masking.
The first example of this link, however, seems to work: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2634.html
Ah, thanks. Expression SFINAE has already been accepted into the current draft, right? Do you know the relevant section numbers? Thanks! Daniel Walker

Mathias Gaunard wrote:
Daniel Walker wrote:
So, I tried your suggestion with gcc 4.4, but I got an error.
Well, to be honest I didn't test it fully. If you call it with a type that doesn't have a foo member function, the overload is indeed masked. I don't know why it doesn't work when using &&, must be a bug.
Of course, the fact that it produces ICE shows it's a bug in itself. I don't really know what really works and what doesn't atm. The first example of this link, however, seems to work: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2634.html
I am fairly disappointed to see it actually doesn't work :(. Hopefully it will be fixed before the 4.4 release.
I hope someone files a bug report :)

Neal Becker wrote:
I could use one to enable a range constructor only where appropriate:
class X { template<typename range_t> X (range_t const&, enable_if<is_range<range_t> >::type *dummy=0)
Question is, what might 'is_range' look like?
It would check whether the type implements the Range concept. Which probably isn't doable in C++03.

on Fri Oct 03 2008, Neal Becker <ndbecker2-AT-gmail.com> wrote:
I could use one to enable a range constructor only where appropriate:
class X { template<typename range_t> X (range_t const&, enable_if<is_range<range_t> >::type *dummy=0)
Question is, what might 'is_range' look like?
I don't think it's really possible to detect it accurately. You can find out if range_begin() is overloaded in range_t's namespace, but when that is namespace boost it's not very useful information because of the default implementations. Maybe we should sink those into a subnamespace and then pull them out with a using declaration. -- Dave Abrahams BoostPro Computing http://www.boostpro.com
participants (7)
-
Alp Mestan
-
Daniel Walker
-
David Abrahams
-
Joel Falcou
-
Mathias Gaunard
-
Neal Becker
-
Steven Watanabe