A potential syntax (as touched in P0587R0) has to take that into account that, If we want to allow concepts to be passed as template parameters,
we don’t want to ambiguate this case with constraining template parameters with concepts.
With Concepts Lite TS, I would intuitively write a template taking a concept as template parameter as:
template<
template<typename> concept MyConstraint
> struct WhateverClass{
template<MyConstraint T> // Use the passed concept here just as “normal”
WhateverClass(T arg){ /* … */ }
};
This is not (yet) allowed but I did not find anyone that even considered it.
Hopefully, I have not missed something.
Cited from the paper:
Conversely, given:
template<int N> concept bool Even = N % 2 == 0;
This seems quite reasonable (if perhaps not all that useful):
template<Even N> void f() {
constexpr Even X = N;
}
Note that in this case, values of type Even are ontologically at the “value” level not at the “type”
level because it is a concept constraining a value (non-type template parameter), not a concept
constraining a type.
There is a problem with that: How do we know what type of template parameter f() actually takes?
Does it refer to a type that is Even? Does it refer to a type ‘Even’, does it refer to an Even value (if yes, what type?) and how do we know, Even is a concept?
We don’t.
If we only can know e.g. the underlying data type (here int) of a concepts use (see template<Even N> void f()) by looking at its definition, this design is significantly flawed.
What my Idea here was is: what if we relax the value constraint with auto (this makes the value constraint reusable and overloadable), see
template<auto N> concept bool Even = N % 2 == 0;
and mention an explicit type (or auto, depending on what we want) at the point of use?
template<Even int N> void f() {
constexpr Even int X = N;
}
This would turn out rather intuitive, doesn’t it?
=> Outcome: Rather than perceiving Even as a constrained Datatype, we can perceive it as a property that we can enforce on the domain of a given type.
But hey! This is nothing but a contract!
[Start note –
In Analogy to the above example:
template<Regular typename T> struct{};
This now makes pretty clear what’s going on here.
-- End note]
I think a great goal we should discuss is merging contracts and concepts together since they portrait the same idea.
The only difference is that one does it at compile time and the other one at runtime (a little bit overgeneralized, but that’s the basic idea, isn’t it?).
If my argument is not clear already, consider the following combined Example:
void f( Positive float m ){
}
void f( NonNull char* dest ){
}
template<
Arbitrary typename T,
Positive int m,
Positive int n
>
void f( Symmetric std::matrix<T,m,n> m ){
}
=> We should try to combine them somehow in a hybrid compiletime/runtime mechanism or else we have a great redundancy between contracts and concepts. (IMO)
These are just a few Ideas that I have not seen anyone talk about. Therfore I'd like to do that now.
I’d be happy to hear from you!
Kind Regards,
Jakob
Hello Folks,Reading P0587R0 (that talks about in what way Concepts might have to be refined),two questions came to my mind, that have not been adressed by any Papers I read about Concepts in C++:
- Allowing concepts to be passed as template parameters.
A potential syntax (as touched in P0587R0) has to take that into account that, If we want to allow concepts to be passed as template parameters,
we don’t want to ambiguate this case with constraining template parameters with concepts.
With Concepts Lite TS, I would intuitively write a template taking a concept as template parameter as:
template<
template<typename> concept MyConstraint
> struct WhateverClass{
template<MyConstraint T> // Use the passed concept here just as “normal”
WhateverClass(T arg){ /* … */ }
};
This is not (yet) allowed but I did not find anyone that even considered it.
Hopefully, I have not missed something.
- How do we make clear if a concept is a value or type constraint?
Cited from the paper:
Conversely, given:
template<int N> concept bool Even = N % 2 == 0;
This seems quite reasonable (if perhaps not all that useful):
template<Even N> void f() {
constexpr Even X = N;
}
Note that in this case, values of type Even are ontologically at the “value” level not at the “type”
level because it is a concept constraining a value (non-type template parameter), not a concept
constraining a type.
There is a problem with that: How do we know what type of template parameter f() actually takes?
Does it refer to a type that is Even? Does it refer to a type ‘Even’, does it refer to an Even value (if yes, what type?) and how do we know, Even is a concept?
We don’t.
If we only can know e.g. the underlying data type (here int) of a concepts use (see template<Even N> void f()) by looking at its definition, this design is significantly flawed.
What my Idea here was is: what if we relax the value constraint with auto (this makes the value constraint reusable and overloadable), see
template<auto N> concept bool Even = N % 2 == 0;
and mention an explicit type (or auto, depending on what we want) at the point of use?
template<Even int N> void f() {
constexpr Even int X = N;
}
This would turn out rather intuitive, doesn’t it?
=> Outcome: Rather than perceiving Even as a constrained Datatype, we can perceive it as a property that we can enforce on the domain of a given type.
But hey! This is nothing but a contract!
[Start note –
In Analogy to the above example:
template<Regular typename T> struct{};
This now makes pretty clear what’s going on here.
-- End note]
On Monday, June 19, 2017 at 6:42:03 AM UTC-7, Jakob Riedle wrote:Hello Folks,
What my Idea here was is: what if we relax the value constraint with auto (this makes the value constraint reusable and overloadable), see
template<auto N> concept bool Even = N % 2 == 0;
and mention an explicit type (or auto, depending on what we want) at the point of use?
template<Even int N> void f() {
constexpr Even int X = N;
}
This would turn out rather intuitive, doesn’t it?
=> Outcome: Rather than perceiving Even as a constrained Datatype, we can perceive it as a property that we can enforce on the domain of a given type.
But hey! This is nothing but a contract!
[Start note –
In Analogy to the above example:
template<Regular typename T> struct{};
This now makes pretty clear what’s going on here.
-- End note]
This strikes me as a great idea. I really hope people see this!I'm skeptical of the perceived similarity between Concepts and Contracts (and I'm skeptical of Contracts in general), but this syntactic idea of putting "typename" or "int" or "auto" after the use of a concept's name seems like a very nice way to keep the human reader "in the loop" about what the code is actually trying to accomplish.Some people (including my former self) would say that "typename" and "auto" are themselves concepts in a sense: "auto" is the placeholder for "any value whose type satisfies <the trivial/top concept>" and "typename" is the placeholder for "any type satisfying <the trivial/top concept>". But with a small syntactic suggestion, you've actually made it really hard for me to see why I ever thought that was a compelling idea. The alternative — that "auto" is a word meaning "this thing here is (has) a value" and "typename" is a word meaning "this thing here is a type" — is not only much easier to read, but strictly in keeping with the way C++11-and-later has always used those words. It seems like a good idea.–Arthur
template<T>
using Z = ConceptA typename T::H<int>;
Does it refer to a type that is Even? Does it refer to a type ‘Even’, does it refer to an Even value (if yes, what type?) and how do we know, Even is a concept? We don’t.
template<int N> concept bool Even = N % 2 == 0;
This seems quite reasonable (if perhaps not all that useful):
template<Even N> void f() {
constexpr Even X = N;
}
1. Using a concept as a template parameter the way you indicate needs a use case to convince me. I think this will be hard to find as the idea of a concept is to define what the actual type has to be capable of to be possible to use. Being able to parameterize this would mean that the code of the function would have to adapt to the _actual concept_ by basically morphing the source code. Isn't this just the opposite of the idea of overloading template functions based on which concepts the actual template parameters fulfill. Thus the code of the two overloads is typically different to handle the different abilities of the actual types of the parameters.When it comes to class templates this becomes more interesting as we currently can't overload them. With concepts available it seems far more reasonable to overload template classes (although there is already a bit strange that you can't overload on the number of template parameters). I guess the current reasoning is to build on the partial specialization functionality and allow class templates to be specialized on the concept level:template<typename T> class my_template {// base implementation};template<Sortable T> class my_template<T> {// optimized implementation using the sortedness of T};I don't recall having seen such an example, but I assume this is how it is supposed to work.2. I didn't know that concepts for non-type template parameters were included in concepts lite. If they are I can imagine that they have not been widely explored... but maybe this is just something that P0355 authors found plausible.You writeDoes it refer to a type that is Even? Does it refer to a type ‘Even’, does it refer to an Even value (if yes, what type?) and how do we know, Even is a concept? We don’t.
regarding this example:
template<int N> concept bool Even = N % 2 == 0;
This seems quite reasonable (if perhaps not all that useful):
template<Even N> void f() {
constexpr Even X = N;
}
I think it is fairly clear that N is a int template parameter. The contents of the {} seems malformed, as Even is not a type. Shouldn't it be "constexpr int X = N;" ?
This said, your suggested syntax with the concept as a prefix of a type or typename has something going for it as it clearly notifies the reader that there is a concept involved without having to find the declaration. Before going much further with this idea we must contemplate if this syntax would work in all places where concepts can be mentioned, and whether it would bloat the code too much to have to type typename in even more places than we currently do.I also find your analogy between concepts and contracts an interesting thought. How about using the new requires keyword on the contract level also?template<typename T> T div_by_two(T x) requires Integral<T> // Compile time requirement{requires x & 1 == 0; // runtime requirement. May be checked by static analyzers and/or compilers, probably depending on buid mode.return x / 2;}Depending on the position and contents of the requires statement(?) it would act as an invariant, precondition or postcondition. I guess you could view this as conceptual requirements just being constexpr contracts possible to evaluate at compile time, but this would make it hard to explain why concept overloading is possible. Inverting that thought would end up with more functional programming:int fac(int x) requires x == 0 // Runtime contract.{return 1;}int fac(int x){return fac(x - 1) * x;}This does not seem that easy to implement, though. Probably a can of worms not worth opening...
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/56bb80fc-cb3d-439e-9746-455df5ddb2d3%40isocpp.org.
template<int N> concept bool Even = N % 2 == 0;
This seems quite reasonable (if perhaps not all that useful):
template<Even N> void f() {
constexpr Even X = N;
}
template<typename N> concept bool EqualComparable = ... ;
This seems quite reasonable (if perhaps not all that useful):
template<EqualComparable N> void f() {
constexpr N my_value;
}
To me it is pretty clear that in the second case N is bound to a type fulfilling EqualComparable concept, while the EqualComparable identifier does not carry any new meaning inside the function compared to outside it.
Thus it seems very strange that the name of the int-valued concept Even should carry special meaning (as an alias of int, maybe?) inside the function. What if you wrote as below, this seems very strange to allow as we immediately break the promise made by using Even as a type.
emplate<int N> concept bool Even = N % 2 == 0;
This seems quite reasonable (if perhaps not all that useful):
template<Even N> void f() {
Even x = N;
x++;
}
No, also strange...
Lots of unfinished thoughs, but may be worth some more experimentation and thinking about what the semantics really should be.
Compare these:template<int N> concept bool Even = N % 2 == 0;
This seems quite reasonable (if perhaps not all that useful):
template<Even N> void f() {
constexpr Even X = N;
}
template<typename N> concept bool EqualComparable = ... ;
This seems quite reasonable (if perhaps not all that useful):
template<EqualComparable N> void f() {
constexpr N my_value;
}
To me it is pretty clear that in the second case N is bound to a type fulfilling EqualComparable concept, while the EqualComparable identifier does not carry any new meaning inside the function compared to outside it.
Thus it seems very strange that the name of the int-valued concept Even should carry special meaning (as an alias of int, maybe?) inside the function. What if you wrote as below, this seems very strange to allow as we immediately break the promise made by using Even as a type.
emplate<int N> concept bool Even = N % 2 == 0;
This seems quite reasonable (if perhaps not all that useful):
template<Even N> void f() {
Even x = N;
x++;
}
You posed this example which shows the same problem, where the 'Even' value is actually odd, oddly enough:template<Even int N> void f() {constexpr Even int X = 3 * N;}Unless this is of course a contrived way of stating that N must be 0...
I really like your idea about viewing concepts as adjectives though. It seems very logical to be able to stack multiple adjectives on a type and maybe on values too:// A function taking an even constant value of some integral arithmetic type, binding the value to the small even number N and the type to decltype(N).template<Arithmetic Integral auto Small Even N> f();Well that could be taking it too far, maybe the type constraints should be on the value constraint definition:template<Arithmetic Integral auto N> concept Even = N % 2 == 0;No, also strange...
Lots of unfinished thoughs, but may be worth some more experimentation and thinking about what the semantics really should be.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/afa41fae-5040-440f-ad0a-5b0a4790980d%40isocpp.org.
// Given:
void f( Even int );
int my_int = 4;
f( my_int ); // warning: implicit cast from 'int' to 'Even int'
f( claim<Even>( my_int ) ); // ok (e.g. Runtime Check with Debug Build, No Check with Release build)
// some sugar if you will?
f( !Even! my_int );
1. Using a concept as a template parameter the way you indicate needs a use case to convince me. I think this will be hard to find as the idea of a concept is to define what the actual type has to be capable of to be possible to use.
// Forward declaration
template<typename T, template<typename T> concept bool... RangeConcepts>
concept bool MultiDimRange;
// Recursive Case
template<
typename T ,
template<typename T> concept bool RangeConcept0 ,
template<typename T> concept bool RangeConcept1 ,
template<typename T> concept bool... RangeConcepts
>
concept bool MultiDimRange<T, RangeCocept0, RangeConcept1, RangeConcepts...> =
Range<T> /* From Ranges TS */
&& RangeConcept0<T>
&& MultidimensionalRange<
ranges::value_type<T> ,
RangeConcept1 ,
RangeConcepts...
>
;
// Base Case
template<
typename T ,
template<typename T> concept bool RangeConcept
>
concept bool MultiDimRange<T, RangeConcept> = Range<T> /* <- From Ranges TS */ && RangeConcept<T>;
// Using the Declarations:
template<typename T>
concept bool MyMatrixType = MultiDimRange<T, RandomAccessRange, RandomAccessRange>;
template<MyMatrixType T>
T matrixMultiply( T m1 , T m2 ){
// e.g.
int i, j;
m1[i][j] // This is defined!
}
1. Using a concept as a template parameter the way you indicate needs a use case to convince me. I think this will be hard to find as the idea of a concept is to
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/56bb80fc-cb3d-439e-9746-455df5ddb2d3%40isocpp.org.
Hi Folks,first of all thank you for your participation and all the constructive replys!Thank you Richard, you managed to express it even more clearly!: "concepts are adjectives, not nouns."As it seems that this Idea is favourited by many people, let's talk about value concepts since I have the strong feeling we should approach all concepts/contracts in the same fashion.Namely I'd like to ask you, in what way contracts do the same thing as concepts and where they do something different.Concepts on types do participate in the type system and thus overload resolution.On the other hand, concepts on values might only be detectable at runtime. Thus overload resolution has no clue about them. Is this desired, given that we want to include mor functional programming into C++?It might have great benefits to include them within the type system as the following example allows to dream:
// Given:
void f( Even int );
int my_int = 4;
f( my_int ); // warning: implicit cast from 'int' to 'Even int'
f( claim<Even>( my_int ) ); // ok (e.g. Runtime Check with Debug Build, No Check with Release build)
// some sugar if you will?
f( !Even! my_int );Besides that, it feels very natural to me to include them into the type system, although I cannot yet say what semantics it should have.
Cheers,Jakob
On Tue, Jun 20, 2017 at 11:45 PM Bengt Gustafsson <bengt.gu...@beamways.com> wrote:1. Using a concept as a template parameter the way you indicate needs a use case to convince me. I think this will be hard to find as the idea of a concept is toHere's my attempt:I'm implementing a type erasure library, and I want to use concepts to check whether types actually fit the archetype of the "typeclass" that I'm erasing. To do that, I'd need to generate a concept per member function name (obviously) to check whether that class has a member with a given name and signature.I can't do this easily, because I need to somehow decompose the function types that my template machinery gives me (as a single type).Now, I'd need either of three things:1) Using concepts as template parameters. This way I could have a type that kind of "explodes" the function type into its parameter. I have that implemented for type templates, and it's extremely useful for this; I can't do it for concepts, for exactly this reason.2) A potentially simpler fix: allowing member concepts of types, because then instead of exploding I could just have a member concept. This is of course the less generic solution, since I'd need a wrapper for every "kind" of a concept, but I could live with it.3) A feature to allow me to specialize concepts - then I can just use the decades old trick of pattern matching on the function type.(Hopefully the usage is clear enough, but I can spend more time on explaining it if it isn't.)
From: Bengt Gustafsson Sent: Wednesday, June 21, 2017 6:28 PM To: ISO C++ Standard - Future Proposals Reply To: std-pr...@isocpp.org Subject: [std-proposals] Re: Clarification needed on Concepts (and Contracts?) |
I can imagine this "runtime overloading" could be useful for things like optional.It is just pattern matching.
At Overloading Resolution, all Functions are equally considered in the sence that there is no ordering of preference other than declaration scope and castability of function parameters.
This however restricts us to function overloads whose concepts are disjunct sets of values (e.g. Even and Odd) in order to prevent ambiguity.In Ordinary Pattern Matching however we have an ordering mechanism: The first one that matches gets taken, regardless of whether a following pattern matches as well.In C++ the only place where you can see a glimps of this mechanism in switch-case, where the first matching branch gets taken:
int a = 0;
switch(a){
case 0: // Matches -> gets taken
break;
default: // matches as well but not taken
break;
}
switch(a){
default: // Matches -> gets taken
break;
case 0: // matches as well but not taken
break;
}
Since you can only resolve this ambiguity by an implicit set of ordering rules (that is, there is no exlicit ordering specified in your code), this can become after all a big source of errors.Therefore I'm agains runtime overloading using concepts as patterns.
/* Don't think about this syntax, I don't like it yet*/
template<typename T>
concept Valid( std::optional<T>& opt ){
return opt.is_valid();
}
std::optional<int> opt = 5;
switch(opt){
case Valid:
//do something with the valid value
break;
case Empty:
//Whatever
break;
}
int f(int x) noexcept [[expects:x>0]];
int f(Positive int x) noexcept;
float algo(float lambda) [[expects:lambda>=0 && lambda<=1]];
float algo(Normalized float lambda);
template<int I>
concept bool PowerOfTwo = /* Is I a power of two? */;
template<PowerOfTwo N>
struct Foo{};
void bar(int N) [[expects: /* Is I a power of two? */]] ;
concept PowerOfTwo(Numerical I){ /* Is I a power of two? */ }
template<PowerOfTwo int N>
struct Foo{};
void bar(PowerOfTwo int N);
template<typename T>
requires is_convertible<T,int>() && is_constructible<T,int>
void func();
// Or even more redundancy to contracts
template<int N>
requires (N % 2 == 0)
void func2();
From: Jakob Riedle Sent: Thursday, June 22, 2017 7:38 AM |
To: ISO C++ Standard - Future Proposals Reply To: std-pr...@isocpp.org |
Subject: Re: [std-proposals] Re: Clarification needed on Concepts (and Contracts?) |
Am Donnerstag, 22. Juni 2017 04:24:47 UTC+2 schrieb Tony V E:I can imagine this "runtime overloading" could be useful for things like optional.It is just pattern matching.I have thought about this for a little now and I found an argument, why we probably don't want pattern matching in the form of runtime overloading:At Overloading Resolution, all Functions are equally considered in the sence that there is no ordering of preference other than declaration scope and castability of function parameters.This however restricts us to function overloads whose concepts are disjunct sets of values (e.g. Even and Odd) in order to prevent ambiguity.
In Ordinary Pattern Matching however we have an ordering mechanism: The first one that matches gets taken, regardless of whether a following pattern matches as well.In C++ the only place where you can see a glimps of this mechanism in switch-case, where the first matching branch gets taken:
int a = 0;
switch(a){
case 0: // Matches -> gets taken
break;
default: // matches as well but not taken
break;
}
switch(a){
default: // Matches -> gets taken
break;
case 0: // matches as well but not taken
break;
}
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/18b35423-7a3f-4aff-8f12-eef1e5b87acb%40isocpp.org.
On Thu, Jun 22, 2017 at 4:38 AM, Jakob Riedle <jakob....@gmail.com> wrote:I have thought about this for a little now and I found an argument, why we probably don't want pattern matching in the form of runtime overloading:At Overloading Resolution, all Functions are equally considered in the sence that there is no ordering of preference other than declaration scope and castability of function parameters.This however restricts us to function overloads whose concepts are disjunct sets of values (e.g. Even and Odd) in order to prevent ambiguity.Well, that's not true. Overload resolution has a whole bunch of priority rules about what constitutes a "better match".
Well, that's blatantly false. The "default" switch case matches if-and-only-if none of the others matches; that's why it's called "default". Also, all of the cases in a switch must be disjoint; otherwise it's a compile-time error.
This has nothing to do with changing behavior based on pattern matching; this has to do with machine verification of formal proofs of program correctness.The big concern I have with this approach to Contracts is that most people hate writing formal proofs, and in fact with the current state of the art, I claim that most people simply won't be able to do it. So it has to remain optional, closeted off in the [[attributes]] ghetto so that it's not part of the "real" syntax, and maybe so that you can quickly turn it off — for build time, or for prototyping, or just to make the dang thing compile. We can't build static-ENSURES()-checking into the language until we can show that it would actually work and not just get in everyone's way.
I believe that if we do go down the current path, and then the path of virtual concepts, actual implementations of the feature will have a lot of work generating these wrappers from the subexpressions. IMO basing the feature on them is a mistake; we should be defining the interface by defining the interface, not by defining its usage.
void foo( Even int );
int i = 5;
foo( i ); // warning: implicit cast from 'int' to 'Even int'.
// This would remind the programmer at the place of the function invokation to check the contracts of the called function.
foo( claim Even(i) ); // implicit runtime check on debug builds, no warning.
// For now, let's ignore the discussion about what happens if the check fails
foo( !Even! i ); // Possible Syntactic Sugar for unary Constraints with same semantic as above
foo( i ); // No warning anymore, since we already claimed i to be Even, that is decltype(i) is 'Even int'
i = 5;
foo( i ); // Again a warning, since we changed i
Iterator iter1 = /*...*/;
Iterator iter2 = /*...*/;
claim Reachable(iter1,iter2); // Turns out to be Synonym to 'REQUIRES( )' resp. '[[expect: ...]]' except that it 'saves' the claimed constraint Reachable(iter1,iter2) for both variables.
// decltype(iter1) is now something like 'Reachable(X,iter2) Iterator' // finding a good textual representation for this type name is irrelevant for now
// decltype(iter2) is now something like 'Reachable(iter1,X) Iterator'
bool is_reachable = Reachable(iter1,iter2); // Only evaluates the constraint
claim i%2==0;
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/b87e09a1-fd8f-48f2-b075-25acc68b1e86%40isocpp.org.
This might be a good way to call them. But I also don't think you necessarily need an "interface interface", in presence of concept maps. Especially since, with if constexpr and proper requires that's usable wherever, you could create default implementations that dispatch to various different kinds of function calls. (In the simplest case, it could just dispatch to the `foo.bar()` call, and that'll work.)
This might be a good way to call them. But I also don't think you necessarily need an "interface interface", in presence of concept maps. Especially since, with if constexpr and proper requires that's usable wherever, you could create default implementations that dispatch to various different kinds of function calls. (In the simplest case, it could just dispatch to the `foo.bar()` call, and that'll work.)The redundancy of concepts to contracts, that I'm talking about, is only present with Concepts Lite (constraining the set of types to those that behave/can be used in a certain desired way). They are redundant in that way, that contracts (if contracts want to represent something more than just asserts, which they currently do) provide the same mechanism for constraining values to those that fulfill the given contract.
Only this redundancy can lead to a unified approach of contracts and concepts.Your approach does something very differnt and has a very different purpose, that is providing a uniform interface for different types, that don't have a uniform interface but only a uniform usage (e.g. operator+ defined as member function or static function). In the same way, enforcing operator+ to be defined as a member function within a concept is analogue to stating that an even number must have an integer datatype (contract).This problem would be completely solved, if we had uniform call syntax for all functions. Then every pointer to member function would be implicitely convertible to a pointer to a freestanding function taking the object as first parameter.In this case we could completely adapt your solution, yes, since it is equivalent to stating the usage of a type, sincethe usage would be homogeneous across all declaration types (memberfn, freestanding fn, etc.) and the declaration type would be indifferent across different usages (invokation through member operator or without).However: I disagree on your point, that if constexpr circumvents this problem. Double type erasure is worse than single type erasure. That means, why do you only erase the implementation, when you can erase the signature as well? Your simplest case is probably the most common but to the extent I understand your comment, this represents double type erasure:
adapting a given type (1st erasure) to be passed to a concept map (2nd erasure).
This basically comes down to the point, that we need uniform call syntax in order to come up with a solution that provides for both applications (Concepts as "contracts based on types") and automatic type erasure (virtual concepts).I really have a bad feeling now with standardizing both contracts and concepts as they are now. They are neither the prettiest nor most elegant solution but instead introduce a rather big redundancy. Given that they represent huge changes to the standard, I am against standardizing them at this point.
What do you think?
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/1cdeeb4c-fcce-4295-9dc0-48b7023a7391%40isocpp.org.
We could be solving three problems - template constraints, type erasure and customization points - by just looking at how other languages implemented typeclasses / traits / whatever, but instead we're spending waaay too much time on a feature that's just SFINAE on steroids (there's a conceptless implementation of the Ranges TS, for crying out loud, and that library supposedly needs concepts...).
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/a92a08bf-d210-4b6d-b728-3d6d8c5fac26%40isocpp.org.
A concept map is what is doing the adaptation.It is a completely compile time thing; a different way to resolve a call (to a thing that could be customized, hence also fixing all our problems that we have with customization points currently). Type erasure is the runtime component, and it just uses the potentially customized calls inside the interface.I'll once again refer to my talk, especially the part after the interludes, that describes those ideas somewhat better than I can in a concise manner in an email.Maybe I should write a paper on this, though it'd probably heavily look like C++0x concepts, and would probably scare half the committee away by being heavy on the use of the phrase "concept maps".
This basically comes down to the point, that we need uniform call syntax in order to come up with a solution that provides for both applications (Concepts as "contracts based on types") and automatic type erasure (virtual concepts).I really have a bad feeling now with standardizing both contracts and concepts as they are now. They are neither the prettiest nor most elegant solution but instead introduce a rather big redundancy. Given that they represent huge changes to the standard, I am against standardizing them at this point.No, we don't need UFCS. We need concepts as interfaces, not as contracts on types, for all the reasons I stated above.
template<typename T>
concept bool LessThanComparable = requires(T a, T b){
bool operator<( T a , T b );
};
template<typename T>
T min1( T a , T b ){
return a < b ? a : b;
}
template<typename T>
requires LessThanComparable <T>()
T min2( T a , T b ){
return a < b ? a : b; // We actually only care about whether the expression 'a < b' is well formed
}
struct Foo{ int bar; };
bool operator<(Foo a, Foo b){ return a.bar < b.bar; }
min1( Foo{4} , Foo{5} ); // This works
min2( Foo{4} , Foo{5} ); // Error: No Foo::operator< defined to fulfill concept LessThanComparable
// Unless you do this (I use the syntax that you used in your talk)
concept_map LessThanComparable<Foo>{
bool operator<(const Foo& lhs, const Foo& rhs) {
return lhs < rhs;
}
};
I think that UFCS would hide the actual problem from us, making it seem as if we solved the adaptation problem, while we would not have actually looked at the problem of customization points that we have all over the place. (std::swap is an ADL mess, operator overloading as free functions is a total mess - see all the issues where `stream << foo` picks up the wrong type by accident, or see how many of those overloads need to be considered before the call is resolved; and a recent shiny one, customization points of structured bindings, which I do mention in the talk linked above, are a terrible, terrible thing.)
We could be solving three problems - template constraints, type erasure and customization points - by just looking at how other languages implemented typeclasses / traits / whatever, but instead we're spending waaay too much time on a feature that's just SFINAE on steroids (there's a conceptless implementation of the Ranges TS, for crying out loud, and that library supposedly needs concepts...).
I think that UFCS would hide the actual problem from us, making it seem as if we solved the adaptation problem, while we would not have actually looked at the problem of customization points that we have all over the place. (std::swap is an ADL mess, operator overloading as free functions is a total mess - see all the issues where `stream << foo` picks up the wrong type by accident, or see how many of those overloads need to be considered before the call is resolved; and a recent shiny one, customization points of structured bindings, which I do mention in the talk linked above, are a terrible, terrible thing.)To me, UFCS really does represent the only solution that allows us to support both worlds with a uniform mechanism (concepts as contracts on types as well as concepts as interface specifications).We could be solving three problems - template constraints, type erasure and customization points - by just looking at how other languages implemented typeclasses / traits / whatever, but instead we're spending waaay too much time on a feature that's just SFINAE on steroids (there's a conceptless implementation of the Ranges TS, for crying out loud, and that library supposedly needs concepts...).C++ has its own ways of doing things already, so in the majority of cases we cannot just incorporate certain approaches of another language to C++.How would you solve template constraints, type erasure and customizations points at once? You need to elaborate a bit more here please.Especially considering: A specification of a type class in Haskell specifies its interface, which is identical to specifying its usage. This is however not the case for C++ as discussed already. So that can't be a solution for C++, unless you presume some sort of UFCS, as discussed above.
Furthermore:What do you think of my approach to contracts in my third last post? Nobody replied anything to it?!Is that because you don't see the similarity of contracts and concepts and the need for approaching them in a uniform fashion?
Cheers,Jakob
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/673b6386-cc71-40b9-9237-925049821c8b%40isocpp.org.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFk2RUZjnnqHZOt0rQx-d%2BdxzdmVVNBjM-ANB5iB1PPt5r5tEw%40mail.gmail.com.
On 28 June 2017 at 14:41, Michał Dominiak <gri...@griwes.info> wrote:
> This is a very emotional mail you've written, which is why I'll only answer
> two parts of it - one of them despite it being not very professional.
Gee, we must disagree on what is or is not emotional. It sure seems to
me that your describing Concepts
as terrible, and deeming SFINAE a better choice, is nothing short of emotional.
> There are no papers that I've written, mostly because it's only now that I'm
> really starting to be involved in the process; but as far as I'm concerned,
> there's been numerous papers describing how they are terrible (and no, I'm
> not going to enumerate them here, because I find it to be a great waste of
> time to point the EWG chair to EWG papers).
I am aware of current papers that propose changes to Concepts, but none of those
papers describe Concepts as terrible in the sense that you seem to do.
> And what I like or not is something you should at least acknowledge, because
> there's a non-zero chance of a new National Body popping into existence in
> WG21 due to my involvement within a timeframe of several months.
That's interesting, hopefully that NB has the ability to send experts
who can actually
explain their views and can think and participate rationally.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFk2RUbucuTZnpfrLLQQDAAwfB5%3DJQnagr8OQhPEtMd-fx-czA%40mail.gmail.com.
On 28 June 2017 at 15:35, Michał Dominiak <gri...@griwes.info> wrote:
>> Gee, we must disagree on what is or is not emotional. It sure seems to
>> me that your describing Concepts
>> as terrible, and deeming SFINAE a better choice, is nothing short of
>> emotional.
> I described what I think we need in detail in this thread. I also described
> in detail how TS concepts relate to what I think we need, and what are their
> shortcomings, IMHO. If you had read this thread, you'd've noticed.
If you want to change how Concepts work, describing it on this thread
does precisely
nothing to achieve that goal.
> There's not a single place where I said SFINAE is a better; there's only a
> place where I say that SFINAE works and can be made not as terrible for a
> general population of C++ programmers with macros; and a separate opinion
> that I gave is that releasing a standard with TS concepts would hurt the
> language. For reasons that I and others have described. What else do you
> want me to do, short of writing a paper? How is actually explaining my
> technical problems with a feature in any way emotional?
Pardon me for misunderstanding "But I, for one, prefer no feature over
bad feature, and I
much prefer writing sfinae over doing TS concepts".
And yes, if you
have something
to say about concepts, you should say it in a paper.
>> > There are no papers that I've written, mostly because it's only now that
>> > I'm
>> > really starting to be involved in the process; but as far as I'm
>> > concerned,
>> > there's been numerous papers describing how they are terrible (and no,
>> > I'm
>> > not going to enumerate them here, because I find it to be a great waste
>> > of
>> > time to point the EWG chair to EWG papers).
>> I am aware of current papers that propose changes to Concepts, but none of
>> those
>> papers describe Concepts as terrible in the sense that you seem to do.
> Sure. Maybe not in the same sense, but there's a clear consensus about a
> lack of consensus, and I personally know quite a few committee members who
> mostly share my opinion on this.
So what are the papers describing how Concepts are terrible, since you said
there are numerous such papers, and I should know what they are?
>> > And what I like or not is something you should at least acknowledge,
>> > because
>> > there's a non-zero chance of a new National Body popping into existence
>> > in
>> > WG21 due to my involvement within a timeframe of several months.
>> That's interesting, hopefully that NB has the ability to send experts
>> who can actually
>> explain their views and can think and participate rationally.
> This is bordering on being inappropriate due to its intent, but I agree with
Sounds like a very liberal interpretation to me.
> the letter (and not the spirit) - I'm more than capable to explain my views,
> and I have done that earlier in this thread (and to an extend in the talk
> that's been linked earlier in this thread). If you want me to explain my
> views verbally (since that'll be easier than throwing emails at each other),
> and you're willing to listen and discuss arguments, then I'll be more than
> happy to discuss this with you in Toronto, should you find some time for it.
I have no use for verbal explanations, std-proposals threads, or
talks. What I have
use for is papers directed at WG21. There can barely be sane
discussion on anything
if the responses to proposals are only ever provided in non-paper form.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFk2RUZZritz2SV3jQTJDJrREKVxEbKAKiQVjpth1RYBO2c_Ow%40mail.gmail.com.
Depending on how the meeting goes and what WG21 decides to do w.r.t. your paper-to-be-a-core-motion of putting the TS into the working paper, I might or might not produce a paper on this topic.
On Wednesday, June 28, 2017 at 9:09:04 AM UTC-4, Michał Dominiak wrote:Depending on how the meeting goes and what WG21 decides to do w.r.t. your paper-to-be-a-core-motion of putting the TS into the working paper, I might or might not produce a paper on this topic.
FYI: you may want to look at the date on the paper he linked to. It was from early 2016, and its purpose was to get the committee to adopt Concepts TS into C++17. It's right there in the abstract.
Since Concepts TS did not go into C++17, you can assume that the paper's goal did not achieve consensus.
Similarly, Gabriel Dos Reis's paper P0606 from early 2017 to blanket adopt Concepts TS as is didn't seem to fly either, since the committee is still debating and considering changes to Concepts.
Now, you should not take that to mean that the committee is going to be willing to consider a page-1 rewrite of concepts the way you want.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/b0b34c4f-cc6a-4680-a957-51cf01308d0f%40isocpp.org.
On 28 June 2017 at 16:08, Michał Dominiak <gri...@griwes.info> wrote:
>> I have no use for verbal explanations, std-proposals threads, or
>> talks. What I have
>> use for is papers directed at WG21. There can barely be sane
>> discussion on anything
>> if the responses to proposals are only ever provided in non-paper form.
> I'm not making a proposal here, I was discussing some ideas and opinions
> about features with other people on this list (and not you in particular).
> Then you came in and demanded that I explain what I've explained earlier. If
> I wanted to have a discussion specifically with you and EWG, I would've
> written a paper. As it is, I was merely having a discussion.
I didn't suggest you're making a proposal, but you seem to have strong opinions
about Concepts as proposed, and apparently a strong preference that something
significantly different should be standardized instead. If you think
that should be
known by the committee and/or the authors of the Concepts proposal, I doubt
you'll reach either of those parties here.
> Does the EWG chair think that discussions of proposed features that are to
> be discussed at the next meeting on std-proposals should be banned? (Yes,
> this is an intentional strawman.)
The EWG chair doesn't care. He also signs his emails when he wants to
emphasize that he's speaking as the EWG chair. See below.
> Bottom line is, you're right - I don't have a paper for this meeting.
> Depending on how the meeting goes and what WG21 decides to do w.r.t. your
> paper-to-be-a-core-motion of putting the TS into the working paper, I might
> or might not produce a paper on this topic. Whether I do or do not produce a
> paper is not, however, going to stop me from discussing this in discussions
> that touch this topic.
That's fine, but I recommend avoiding being disappointed if you have
very strong views
and concerns on Concepts or any proposal going on in the committee,
and the committee fails to address
your concerns because it has never heard of them.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFk2RUYJwir2uPkxcOAVKPgbW5ey5apMCRfSk98hWD7%2BCjctSQ%40mail.gmail.com.
Well, it's not quite democratic, it's very representational in the
sense that voting
members must be ISO voting members, and to be that, they must be NB members
as well. ;)
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFk2RUYaW6kNmo1u-KEUskK2HGr-4wQhtD8bCiQ7VjcA4tbo9g%40mail.gmail.com.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFk2RUb6%2Bg7DDt1dN3L-KGDxT5Yc4MG0JiOZ%2BOof7tFZdDJh8g%40mail.gmail.com.
I have no illusion of your reading this paper, but perhaps it will show to some others why SFINAE is laughably inferior:
http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0225r0.html