is_range metafunction

classic Classic list List threaded Threaded
27 messages Options
12
Reply | Threaded
Open this post in threaded view
|

is_range metafunction

Neal Becker
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
Reply | Threaded
Open this post in threaded view
|

Re: is_range metafunction

Alp Mestan-2
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 <[hidden email]> 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
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: is_range metafunction

Neal Becker
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 <[hidden email]> 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).

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: is_range metafunction

Mathias Gaunard-2
In reply to this post by Neal Becker
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.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: is_range metafunction

Mathias Gaunard-2
In reply to this post by Neal Becker
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.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: is_range metafunction

Dave Abrahams
In reply to this post by Neal Becker

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
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: is_range metafunction

Steven Watanabe-4
In reply to this post by Mathias Gaunard-2
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

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: is_range metafunction

Daniel Walker-4
On Fri, Oct 3, 2008 at 5:59 PM, Steven Watanabe <[hidden email]> 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
Reply | Threaded
Open this post in threaded view
|

Re: is_range metafunction

Dave Abrahams
The answer is yes.

Sent from my iPhone

On Oct 5, 2008, at 6:06 PM, "Daniel Walker"  
<[hidden email]> wrote:

> On Fri, Oct 3, 2008 at 5:59 PM, Steven Watanabe  
> <[hidden email]> 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
>
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: is_range metafunction

Daniel Walker-4
On Sun, Oct 5, 2008 at 6:47 PM, David Abrahams <[hidden email]> 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
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: is_range metafunction

Mathias Gaunard-2
In reply to this post by Daniel Walker-4
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.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: is_range metafunction

Daniel Walker-4
On Sun, Oct 5, 2008 at 7:54 PM, Mathias Gaunard
<[hidden email]> 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
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: is_range metafunction

Dave Abrahams
In reply to this post by Daniel Walker-4

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 <[hidden email]> 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
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: is_range metafunction

Daniel Walker-4
On Sun, Oct 5, 2008 at 9:39 PM, David Abrahams <[hidden email]> 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
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: is_range metafunction

Mathias Gaunard-2
In reply to this post by Daniel Walker-4
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)

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: is_range metafunction

Joel Falcou-2
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 ?
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: is_range metafunction

Daniel Walker-4
In reply to this post by Mathias Gaunard-2
On Mon, Oct 6, 2008 at 6:58 AM, Mathias Gaunard
<[hidden email]> 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
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: is_range metafunction

Daniel Walker-4
In reply to this post by Joel Falcou-2
On Mon, Oct 6, 2008 at 7:02 AM, Joel Falcou <[hidden email]> 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
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: is_range metafunction

Joel Falcou-2
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 ?
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: is_range metafunction

Mathias Gaunard-2
In reply to this post by Daniel Walker-4
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.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
12