|
Boost : |
From: David Abrahams (dave_at_[hidden])
Date: 2006-05-08 13:44:03
Tobias Schwinger <tschwinger_at_[hidden]> writes:
> I went through the code just yesterday, so...
>
> The guessing stuff directly in 'is_sequence' is a workaround for
> broken compilers. For proper compilers:
>
> is_sequence<T> <=> is_same< begin<T>, void_ >
>
> . So 'is_sequence' works perfectly well and can also work perfectly
> reliable given that 'begin' does; 'begin', however, fails to compile
> if there is a 'tag' member for a non-sequence type instead of
> returning 'void_' which would be the documented behaviour.
And begin can be spoofed, too, can't it? Okay, it's very unlikely.
> The reason is "guessing mess" in 'begin_impl': the primary template
> attempts to return 'T::begin' (it seems to be a convenience feature so
> a sequence implementor can simply specify a type member called 'begin'
> and does not need to specialize 'begin_impl'). 'sequence_tag' is
> assumed to sort out non-sequences -- but it is impossible without
> guessing (or adding to the user's responsibilities when registering
> non-sequence types for tag dispatch).
Exactly.
>>>>>
>>>>>I don't see why it is impossible. MPL sequences can always
>>>>>specialize is_sequence<T>. is_sequence *can* work reliably
>>>>>100% of the time:
>>>>> template <class S> struct is_sequence : mpl::false_ {}; //
>>>>> default
>>>>> // your specializations here
>
> That should not even be needed -- implementing 'begin' should be
> enough...
I am not thinking about this problem freshly today; all I remember is
that it's a morasse with no good answers. But I could be wrong. If
you can supply a patch that works, and you can demonstrate it with
convincing tests, I'll be happy to recommend that Aleksey commit it.
>>>>The problem isn't false negatives, it's false positives. In
>>>> practice
>>>>you can probably make it vanishingly unlikely that some random
>>>>third-party type will pass all the default is_sequence tests, but
>>>> you
>>>>can never make it 100% impossible as long as:
>>>> a. sequences can be arbitrary types, such as void(int,long,char)
>>>> b. is_sequence<S> reporting correctly is not part of the sequence
>>>> requirements
>
> c. begin works properly
>
> 'begin<non_sequence>::type' being 'void_' (maybe more importantly that
> it compiles) is already part of the requirements...
Yes but it *totally* begs the question. Because, what do you have to
know in order to decide whether begin<x> should return void_? That's
right, you have to know whether x is a sequence.
>>>I believe that the default is_sequence should strictly be
>>>mpl::false_: no guessing games.
>>>
>>>I think:
>>>
>>>a) if you want to make specific types (e.g. RT(A0,A1,...AN)),
>>>a sequence, then specialize is_sequence for those.
>>
>>
>> ODR violations ensue. int(int,long) is a sequence in one TU but not
>> in another.
>
> Just curious: all these classes should have internal linkage - am I
> missing something?
foo<is_sequence<int(int,long)>::value>::bar() calls one function in TU
#1 and another function in TU #2. Clear yet?
> So here's my â¬0,02-plan:
>
> -- require 'begin_impl' to be specialized; IOW drop that "type member
> convenience stuff" (described above) -- it is what makes the dispatch
> a mess! -- throw out 'sequence_tag' (it doesn't work, can't work and
> isn't needed) -- keep 'is_sequence' ;-)
Show me the money. Err, the code.
-- Dave Abrahams Boost Consulting www.boost-consulting.com
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk