On 3/13/2013 5:36 PM, Andrew Sutton wrote:
Let me take this opportunity to remind people that
"being able to do something is not sufficient reason for doing it" and
"being able to do every trick is not a feature but a bug"
For the latter, remember Dijkstra's famous "Goto considered harmful"
paper. The point was not that the "new features" (loop constructs) could
do every goto trick better/simpler, but that some of those tricks should
be avoided to simplify good programming.
Concepts and concepts lite are meant to make good generic programming
simpler. They are not meant to be a drop-in substitute for every
metaprogramming and macroprogramming trick. If you are an expert, and if
in your expert opinion you and your users really need those tricks, you
can still use them, but we need to make many (most) uses of templates
easier to get right, so that they can become more mainstream. That where
concepts and concept lite fits in.
Some of you may find this hard to believe, but "back then" there was
quite serious opposition to function declarations because "they
restricted the way functions could be used and the way separate
compilation could be used" and also serious opposition to virtual
functions "because pointers to functions are so much more flexible." I
see concepts lite (and concepts) in the same light as goto/for,
unchecked-function-arguments/function-declarations,
pointers-to-functions/abstract-classes.
>> In general, it's a subset of an actual (complete) set of requirements
>> that can be checked during overload resolution (and contributes to
>> determining the outcome of an overload resolution process).
> In general, that should *not* be. Remember that concepts-lite is an
> incremental step towards a full concepts, it's not simply a
> replacement for enable_if.
>
> Concepts will definitely include requirements for separately checking
> template declarations separately from their instantiation, which means
> that names and expressions that would result in substitution failures
> now may result in compiler errors in the future.
>
> SFINAE hacks have enabled programmers to think about only what's
> necessary to achieve a particular overloading outcome, but not the
> complete set of requirements for a template. I'm as guilty of that as
> anybody, but I also understand that what can do using SFINAE is not
> the equivalent of a proper specification.
>
>
>> A possible impression that formally constrained and formally
>> unconstrained templates should always mix well is just an illusion.
> Are you suggesting that future libraries should contain a mix of
> SFINAE-enabled overloads mixed with constrained overloads? Can you
> provide some rationale as to why that would be the case?
>
>
>
>> How exactly would you define the concept? That's the most interesting
>> part. Also it would be interesting to see a concept-based alternative
>> to the following definition of min:
>>
>> #define FORWARD(x) static_cast<decltype(x) &&>(x)
>>
>> #define RETURN(...) \
>> noexcept(noexcept(__VA_ARGS__)) \
>> -> decltype((__VA_ARGS__)) \
>> { return __VA_ARGS__; }
>>
>> template <class T1, class T2>
>> auto min(T1 &&t1, T2 &&t2)
>> RETURN(t1 < t2 ? FORWARD(t1) : FORWARD(t2))
>>
>> BTW, within the model described in N2914 (the last C++0x working draft
>> with concepts) it's extremely hard (or impossible?) to specify correct
>> constraints for such min.
> Did you read the entire proposal? The implementation section described
> the mechanism I used to implement syntactic requirements, and if you
> dig through the implementation of the traits header, you'll see how
> the noexcept type traits are implemented using constraints. It's in a
> file named include/bits/cons_type_traits.h (in libstdc++v3).
>
>
> template<typename T, typename U>
> requires Totally_ordered<T, U>()
> Common_type<T, U>
> min(T&& t, T&& u) { return t < u ? t : u; }
>
> The implementation of Concepts Lite does not yet include Common_type
> --- I left it out on accident, but there's a good definition in the
> Palo Alto TR (N3351). It's the result type of the ?: operator.
>
> Add forwarding where appropriate, but I don't think it should be necessary.
>
>
>>> This is not a convincing argument for conflating the difference
>>> between an interface and an implementation.
>> What is the difference between interface and implementation of a call
>> wrapper that simply forwards arguments to and results from some
>> underlying function? What is the point to define a special concept for
>> such wrapper?
> If you find the need to define a special concept for such a wrapper,
> then I suspect that particular function does not need to be
> constrained, or could be adequately defined using some SFINAE
> mechanism.
>
> Andrew
>
|