Clarification needed on Concepts (and Contracts?)

348 views
Skip to first unread message

Jakob Riedle

unread,
Jun 19, 2017, 9:42:03 AM6/19/17
to ISO C++ Standard - Future Proposals
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++:

  1. 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 dont 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.

 

 

  1. 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 dont.

 

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, doesnt 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 whats 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 thats the basic idea, isnt 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.

 


Id be happy to hear from you!

 

Kind Regards,

Jakob

 

Arthur O'Dwyer

unread,
Jun 19, 2017, 7:28:47 PM6/19/17
to ISO C++ Standard - Future Proposals
On Monday, June 19, 2017 at 6:42:03 AM UTC-7, Jakob Riedle wrote:
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++:

  1. 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 dont 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.


I don't know anything authoritative about this, but my random uneducated intuition is that either:
(A) given their extremely templatey syntax, concepts are just templates, and so you can write
    template<template<typename> bool MyConstraint>
    struct WhateverClass {
        template<MyConstraint T> WhateverClass(T arg) { ... }
    }
or else (B) concepts operate at a higher level than templates, just as types operate at a higher level than values, and so there are philosophical problems with the entire idea of making a templated type based on a concept.  (But I don't think this is the case.)


  

  1. 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 dont.

 

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.


We have the same problem with type-concepts in general: given
template<Foo f> struct S { ... };
I have no way of knowing whether Foo is the name of a literal type (so I should say S<Foo{x}>) or the name of a concept (so I should say S<Bar>). And now you're saying it could even be a value constraint (so I should say S<Bar{x}>)? Gross.

 

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, doesnt 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 whats 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

inkwizyt...@gmail.com

unread,
Jun 20, 2017, 4:14:28 PM6/20/17
to ISO C++ Standard - Future Proposals


On Tuesday, June 20, 2017 at 1:28:47 AM UTC+2, Arthur O'Dwyer wrote:
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, doesnt 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 whats 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

I agree with that, this fix too small insincerity with using terse syntax, because `Concept A`  mean different thing in context of template params and function arguments.
With this it will always mean "define object/argument A that fulfills concept" and in template we will use `Concept typename T` to define type.

This bring another thought, why do not allow use this new syntax in type alias declaration or other similar contexts? something like that:

template<T>
using Z = ConceptA typename T::H<int>;

Now `Z` work only if `T::H<int>` fulfills `ConceptA`.

Overall concepts would become prefixes for `typename` keyword.

Bengt Gustafsson

unread,
Jun 20, 2017, 5:45:31 PM6/20/17
to ISO C++ Standard - Future Proposals
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 write

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 dont.


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...

Richard Smith

unread,
Jun 20, 2017, 6:11:03 PM6/20/17
to std-pr...@isocpp.org
On 20 June 2017 at 14:45, 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 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 write

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 dont.


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;" ?

No, that's exactly the point: in the template parameter list, Even *is* acting as a type. It would be logical that you could use it in the same semantic role elsewhere too.


I find the suggestion here very interesting, and it's made me realise something that seems fundamental: concepts are adjectives, not nouns. There's no such thing as a Regular, or an EqualityComparable, but there clearly are Regular types and EqualityComparable types. Based on that, it makes perfect sense to me that we should be able to write

void f(Regular auto x);

or even

void f(Regular EqualityComparable InputIterator auto x);

Likewise, it makes sense to be able to write

template<Regular EqualityComparable InputIterator typename T>
void f(T x);

and we can then easily distinguish between:

template<Integral typename T>

and

template<Integral auto T>

(where the former takes an Integral type and the latter takes a value of an Integral type), and likewise we could write:

template<Even int N> void f() {
  constexpr Even int X = 3 * N;
}

If desirable, the "natural notation" could then be obtained by omitting the "auto" in a terse function template declaration:

void f(Regular x); // implicitly means "Regular auto x"

... in much the same way that we can leave out the "int" in "unsigned long x".

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.

Bengt Gustafsson

unread,
Jun 20, 2017, 7:19:32 PM6/20/17
to ISO C++ Standard - Future Proposals
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.

Richard Smith

unread,
Jun 20, 2017, 9:35:45 PM6/20/17
to std-pr...@isocpp.org
On 20 June 2017 at 16:19, Bengt Gustafsson <bengt.gu...@beamways.com> wrote:
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.


I don't follow what you're saying about new meaning inside / outside the function. If we permitted the above, we would presumably also permit

constexpr Even x = 42;

... at global scope. (And Even would have the same meaning in every context: it introduces the name of an integer whose value is even.)

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;


This would be ill-formed, as the value of x cannot be statically checked to satisfy the Even concept (Even<x> does not evaluate to true). You'd at least need x to be const.

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 think you should think about this a bit more :-)

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.


It's interesting that even the "taking it too far" case still seems pretty readable to me. This direction seems to have some very nice properties.
 

--
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.

Jakob Riedle

unread,
Jun 21, 2017, 5:18:26 AM6/21/17
to ISO C++ Standard - Future Proposals
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.



Am Dienstag, 20. Juni 2017 23:45:31 UTC+2 schrieb Bengt Gustafsson:
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.

The reason I had the idea was an actual use case: Defining a Concept that describes a Multidimensional Datastructure. Expressing this is done in analogy to a range of ranges of ranges and so on... (to the depth you want it)
Since we don't want to restrict ourself to a specific class of Ranges, the 'MultidimensionalRange' Concept is itself templated with concepts.

With the Concepts of Ranges TS (and the Syntax of Concepts Lite, extended with concepts as template parameters):
 
// 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!

}


I don't know if concepts will be passed as template parameter to non-concepts, but they will definitely need to be passed as template parameters to other concepts to refine them.

Cheers,
Jakob

Michał Dominiak

unread,
Jun 21, 2017, 5:56:13 AM6/21/17
to std-pr...@isocpp.org
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 to

Here'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.)
 
--
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.

Bengt Gustafsson

unread,
Jun 21, 2017, 6:28:39 PM6/21/17
to ISO C++ Standard - Future Proposals


Den onsdag 21 juni 2017 kl. 11:18:26 UTC+2 skrev Jakob Riedle:
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.
To me it is not totally obvious that "as concepts on values might only be detectable at runtime overload resolution has no clue about them."
Many functional languages actually do implement runtime dispatching to different implementation based on parameter values, and it is conceivable that when using a concept like Even as the type of a normal function parameter this could be a way to indicate that a runtime dispatch subroutine has to be created:

f(Even x) { cout << "Even"; }
f(Odd x) { cout << "Odd"; }

for (int i = 0; i<2; i++)
    f(i);

prints:
EvenOdd

The call site or a stub would have to be compiled to code containing an if on i, but I don't see that as hard to do. The scary part is the variability of the overload set, sometimes forcing creation of multiple stubs depending on how many function overloads have been seen.

Also note that in the absence of the f(Odd x) declaration this could degenerate to an assert that x is Even as there is no overload to call otherwise.

While I'm not advocating for such an idea (at least not yet) I would say it is premature to rule it out, given that this is how some other languages deal with the situation...
Wow. This gets compliacated. Does this code compile with the concept aware GCC version?

I have a related issue I was aiming to bring up in a separate thread, but as you started discussing multi-dimensional arrays I will out it here:

Is it possible to write a concept requiring that the multi-dimensional matrix must have an overloaded operator() with as many indices as there are dimensions? Is it even possible to write a concept that specifies that there should be a method of a certain name that takes a unbounded number of parameters? 

I have not understood how as in concepts-lite you write "example code" to express requirements, and there seems to be no way to exemplify that a method must be callable with any number of parameters short of listing each case... With the old concepts where requirements were formed as method declarations this would have been natural, just write your template<typename... Ts> my_fun(const Ts... ts) thingy.

A lesser version of this limitation also exists in the concrete template<size_t RANK> class Matrix; case where you can't specify that an operator() with RANK number of parameters exists, this will be revealed only at the last recursive template instantiation step, just one of those things that concepts should alleviate. I hope they do, but I for one can't figure out how to specify it.


 
Cheers,
Jakob

Bengt Gustafsson

unread,
Jun 21, 2017, 6:36:33 PM6/21/17
to ISO C++ Standard - Future Proposals
I think you may have to elaborate to make this more understandable. To me it seems that your use case just calls for a regular concept for the type to be erased, which describes each method that the type erasing wrapper has.



Den onsdag 21 juni 2017 kl. 11:56:13 UTC+2 skrev Michał Dominiak:
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 to

Here'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.)

I think you may have to elaborate to make this more understandable. To me it seems that your use case just calls for a regular concept for the type to be erased, which describes each method that the type erasing wrapper has. I could speculate that your trying to make a "general typ erasor" where each method of the wrapped archetype is a member function template parameter or something like that, if so it clearly needs more explanation. Also maybe it could be taken as proof for the need for virtual concepts (or proxies as they are called in another nearby thread).


 
 

Tony V E

unread,
Jun 21, 2017, 10:24:47 PM6/21/17
to ISO C++ Standard - Future Proposals
I can imagine this "runtime overloading" could be useful for things like optional. 
It is just pattern matching.

Sent from my BlackBerry portable Babbage Device
From: Bengt Gustafsson
Sent: Wednesday, June 21, 2017 6:28 PM
To: ISO C++ Standard - Future Proposals
Subject: [std-proposals] Re: Clarification needed on Concepts (and Contracts?)

--
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.

Jakob Riedle

unread,
Jun 22, 2017, 7:38:01 AM6/22/17
to ISO C++ Standard - Future Proposals


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;
}

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.

Instead, I think allowing something like pattern matching in the form of:
/* 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;
}

Since pattern matching in this form is a different proposal and since Concepts/Contracts don't depend upon it, I'd rather not waste time now talking about it. I feel we need to make progress with the meat of the topic first.
That is for me, how can we merge contracts and concepts?. If you need reasons, why this is desirable:
  1. Contracts (as introduced by P0380R1) are not meant to be reusable that the meaning behind them cannot be expressed as a NAME: [Cited from the Paper]
    int f(int x) noexcept [[expects:x>0]];
    Rather it would be way more intuitive to write
    int f(Positive int x) noexcept;
    No only is this shorter but it also transports the meaning of what x>0 means.
    Another example:

    float algo(float lambda) [[expects:lambda>=0 && lambda<=1]];

    float algo(Normalized float lambda);
    The former is not only more descriptive, it is more readable and furthermore reusable.

  2. The Redundancy comes into play, when we mix value concepts and contracts
    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? */]] ;
    Instead we can write e.g.
    concept PowerOfTwo(Numerical I){ /* Is I a power of two? */ }

    template<PowerOfTwo int N>
    struct Foo{};

    void bar(PowerOfTwo int N);
Summary:
  • Contracts restrict the domain of a datatype to a set of values at runtime.
  • Concepts Lite restrict the set of types (or the domain of a datatype in case of value concepts as touch previously in P0587R1) at compile time.
Contracts target use cases where you don't want to give a name to a property that you enforce on your types.
This is equivalent to the requires keyword from Concepts that you can use above function declarations (take this as indication that they are indeed portraiting the same idea):
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();

Tony V E

unread,
Jun 22, 2017, 8:11:55 AM6/22/17
to ISO C++ Standard - Future Proposals
Good point about ordering. 
P.S. There is another place that does ordered pattern matching - catching exceptions.

Sent from my BlackBerry portable Babbage Device
From: Jakob Riedle
Sent: Thursday, June 22, 2017 7:38 AM
To: ISO C++ Standard - Future Proposals
Subject: Re: [std-proposals] Re: Clarification needed on Concepts (and Contracts?)

--
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.

Arthur O'Dwyer

unread,
Jun 22, 2017, 2:04:28 PM6/22/17
to ISO C++ Standard - Future Proposals
On Thu, Jun 22, 2017 at 4:38 AM, Jakob Riedle <jakob....@gmail.com> wrote:
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.

Well, that's not true. Overload resolution has a whole bunch of priority rules about what constitutes a "better match".

template<class T> void f(T t) { puts("worst match"); }
template<class T> void f(T *t) { puts("better match"); }
template<class T> void f(T **t) { puts("best match"); }
int main() { void ****p; f(p); }

(These are three different overloaded function templates, not a base template and two partial specializations.)
My impression is that Concepts Lite proposes a similar hierarchy of concepts, since that's kind of the purpose of having Concepts in the language at all. It may not always be implemented properly, but I believe it's supposed to work.

template<InputIterator T> void f(T t) { puts("worst match"); }
template<ForwardIterator T> void f(T t) { puts("better match"); }
template<RandomAccessIterator T> void f(T t) { puts("best match"); }
int main() { int *p; f(p); }

 
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;
}

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.

int main() {
    switch (42) {
        default: puts("not taken"); break;
        case 42: puts("taken"); break;
    }
}

Tony identified a case that does kinda-sorta work this way, though: catch-handler chains. They're always implicitly nested, just like if-else chains.

if (x) {
} else if (true) {
} else if (z) {
}

really means

if (x) {
} else {
    if (true) {
    } else if (z) {
    }
}

and similarly

try {
} catch (x) {
} catch (...) {
} catch (z) {
}

really almost means

try {
    try {
        try {
        } catch (x) {
        }
    } catch (...) {
    }
} catch (z) {
}

except that if you re-throw from one of those inner catch handlers, it will not be caught by the outer handlers.
FWIW, the problem I always have whenever anyone tries to explain Contracts to me this way is: there's no such thing as "restricting" behavior at runtime! What you really mean is, "At runtime, if this situation arises, then <do something>."  And C++ already has tons of ways to express that.
In other words, Concepts Lite provides a way to say, "If this condition isn't satisfied, then SFINAE away: do the next-best thing if there is one."  But with Contracts, all we can say is, "If this condition isn't satisfied, then the code has a bug and we need to hard-fail." So these Contracts are not the runtime equivalent of SFINAE/Concepts; these Contracts are the runtime equivalent of static_assert().  But C++ has had the runtime equivalent of static_assert() for longer than we've had static_assert()!  :)


However, at C++Now I had a long talk with Lisa Lippincott and she had a way of looking at Contracts that at least was self-consistent (although I cannot judge how much it is in step with the mainstream at the current moment).  Forget runtime. Contracts are about annotating code with annotations ("contracts") that can be statically checked at compile-time. That is, they're the equivalent of the semi-common practice

#define REQUIRES(x) assert(x)
#define ENSURES(x) assert(x)

int log2(int x)
{
    REQUIRES((x & (x-1)) == 0);
    int r = 0;
    while (x != 1) x >>= 1, ++r;
    ENSURES(0 <= r && r <= 31);
    return r;
}

(logic bugs in the above code are somewhat intentional).
The hope is that by religiously annotating every speck of code with these preconditions and postconditions, the compiler will actually be able to check your "correctness proof" and verify that each ENSURES clause follows logically from its corresponding REQUIRES clauses and the code in between.

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.

my $.02,
Arthur

Michał Dominiak

unread,
Jun 22, 2017, 3:58:08 PM6/22/17
to std-pr...@isocpp.org
It'll probably be easiest if I point to slides from my C++Now talk, you can go watch it if you wish so: https://github.com/boostcon/cppnow_presentations_2017/blob/master/05-19-2017_friday/customization_points_that_such_less__michal_dominiak__cppnow_05-19-2017.pdf. The interesting slides are 55 onwards.

I create a structure defining the interface for the type erased "concept", and then I create mixins that provide those members for various elements of the machinery. Now, slides 63 onwards show what I'd like to do with concepts somehow. I can only operate on function types, and while I can pass the function types into concepts, I can't decompose them in any way.

Bottom line is: I need to be able to define a concept's body in a place where I have access to the decomposed elements of the function type. Currently it's literally impossible.


As for virtual concepts -- yeah, and I do also mention them in the slides. But I can't use concepts to define the interface for my library -- there's no way to iterate over all the subexpressions that need to compile for the concept to be true, to generate a mechanism for invoking them through the type erasure wrapper. I have to do it through an actual interface -- which, coincidentally, looks exactly like Haskell typeclasses, Rust traits, ..., ...

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. I believe there's no prior art on this in the field, which makes the C++ approach a research project, which is not a great fit in a mainstream programming language's core. (I wish we iterated a few more times on this in form of TS revisions.)
 

--
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.

Jakob Riedle

unread,
Jun 22, 2017, 6:40:18 PM6/22/17
to ISO C++ Standard - Future Proposals
Hey Guys,

Am Donnerstag, 22. Juni 2017 20:04:28 UTC+2 schrieb Arthur O'Dwyer:
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".

As I said, "no ordering of preference other than declaration scope and castability of parameters". I mean exactly what you said :D


Am Donnerstag, 22. Juni 2017 20:04:28 UTC+2 schrieb Arthur O'Dwyer:
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.

I think you got me down the wrong pipe. I know what pattern matching is and how it works and I know that it is not, what switch-case does.
I am sorry for posting this example about switch-case, it apparently does nothing to clarify any of the meat discussed in this thread.


Am Donnerstag, 22. Juni 2017 20:04:28 UTC+2 schrieb Arthur O'Dwyer:
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.

Yeah, I understand the problem a little bit more now. I had a new Idea concerning this while writing this answer, I'll append it to the end.


Am Donnerstag, 22. Juni 2017 21:58:08 UTC+2 schrieb Michał Dominiak:
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.

Yes this hits the nail right on top I think. Isn't the problem 'just', that we want to use a specific operation of/on a type and want it to be defined but don't want to care about how, where and as what it is implemented?
The problem here is IMO that operations can be defined in many ways (member function, static function, object with operator() overloaded ...), still they can share the same invocation syntax.

Actually, I would not call an interface what you call interface.
In the context of concept definitions, IMO defining the usage of a feature is defining an abstract interface (even more abtract than in form of a function signature). [An interface of an interface, if you will.]
This way, many implementations of that feature (as freestanding function, member function, constructor) can fulfill it.

After all I think this Proposal is quite doable, but you probably are referring to this as well.



Appendix:

Contracts are part of the type system but are not statically checked. However in Debug Builds, whenever there is an implicit cast from an unconstrained value to a constrained one, a warning and an implicit runtime check is generated.
Whenever we want to ellide this warning (not the runtime check, for this you have to switch to release build mode), you write something with the semantics of 'claim ... is ...'.
This can be within a function call, Assignment Operation or outside of it (as are Ensures and Expects). Result of this claim operation is always the value itself.
However after the claim, the definition of the variable being claimed to fulfill a given concept is changed to include this claim. This happens to the point, where the variable is changed again.
Example:
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

To claim an unnamed constraint, you would write for example
claim i%2==0;

In contrast to assert, REQUIRES and [[expects: ]], claim (or whatever name we may choose) would probably be an operator and it changes the declared type of the involved variable for all future uses of it (below the call to claim).
Allowing the constraints to be part of the type system and thus allowing them to be part of a function declaration resembles the idea that the caller is responsible for passing in the right values (a contract), instead of the idea of values being checked within the function.

Sure, many aspects of this approach are not determined yet and may even be a rather big discussion point... BUT:
By using this approach,
  1. you provide the tools for formal verification/static analysis (to the extent that programmers annotate their code), you
  2. have everything compile as usually (no errors, just warnings), you
  3. conditionally support runtime-checks as described in P0380R1, you
  4. can reuse the defined constraints for future pattern matching proposals and you
  5. bridge the gap between value concepts and contracts (as 'constexpr' constraints are usable for template parameters as well).
I hope I have not forgotten something essential, please have mercy with me in this case :D

Cheers and have a nice Evening,
Jakob

Jakob Riedle

unread,
Jun 27, 2017, 5:31:25 AM6/27/17
to ISO C++ Standard - Future Proposals
Michael? Arthur? Are you there?

Michał Dominiak

unread,
Jun 27, 2017, 6:43:29 AM6/27/17
to std-pr...@isocpp.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.)

Now, this has the advantage of providing customization points, and all this very naturally leads to type erasure (which is extremely powerful, because you can adapt types that don't fit!).

Virtual concepts is a thing I often refer to, and while I believe that'd be a necessary thing to have if we end up with the TS concepts, I'd much prefer not to end up with TS concepts and have a way to specify an (adaptable - this is a truly crucial point, because it allows me to do semantic specializations, not just a syntactic one, by providing an "explicit" concept thing, which stops types accidentally matching an interface) interface instead of specifying an interface interface.

And now the crazy part: I think we can implement all that with metaclasses. I still want a language feature, because that'd make it easier to avoid mixing a concept kind with a type kind, but it could be done. If someone gave me a way to create a new kind of an entity in the language, I could have an implementation I'd be happy with with metaclasses. (I don't know whether having a generic facility to introduce new entity kinds would be a popular idea for C++. Up until this very moment I haven't even considered it for a research language that I'm working on, which usually ends up being the bag to put features I eventually want to implement in.)
 
--
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.

Jakob Riedle

unread,
Jun 27, 2017, 9:49:26 AM6/27/17
to ISO C++ Standard - Future Proposals
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, since
the 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?

Michał Dominiak

unread,
Jun 27, 2017, 10:01:45 AM6/27/17
to std-pr...@isocpp.org
On Tue, Jun 27, 2017 at 3:49 PM Jakob Riedle <jakob....@gmail.com> wrote:
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, since
the 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).


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.
 
What do you think?

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...).

--
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.

Nicol Bolas

unread,
Jun 27, 2017, 12:55:55 PM6/27/17
to ISO C++ Standard - Future Proposals
On Tuesday, June 27, 2017 at 10:01:45 AM UTC-4, Michał Dominiak wrote:
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...).

And in so doing, take another 5 years to get it done while simultaneously doing nothing about having a usable form of compile-time checking for static polymorphism in the language. How many C++ programmers can actually write that concept-less version of Ranges TS? And how many could write it with Concepts TS? I'd bet that the number in the latter is several orders of magnitude greater than the former.

At some point, you've got to get something done. Concepts TS isn't the best it could be, and I really want to see some changes to the proposal (and I really hope the committee rejects Stroustrup's "everything is awesome" approach to integrating the TS with the standard). But saying that we ought to ditch it and start from scratch, just because you think you could do better is not productive.

If you had a better idea, you could have been working on it in parallel with Concepts TS. You could have gotten together with people and wrote a proposal with standards wording, forked Clang and implemented it, and proven your point. After all, Concepts Lite was able to do those things. Right now, you are nothing but words, while Concepts TS is a real, live, and useful feature of C++.

Michał Dominiak

unread,
Jun 27, 2017, 2:53:18 PM6/27/17
to ISO C++ Standard - Future Proposals
Yes, splendid. Let's get a terrible feature in because we prefer that over nothing. This has never caused any problems for anyone, right?

About the only thing I like from the TS is the requires expressions in any context and the requires clauses on declarations. Pulling more stops us from ever having a truly good feature dealing with this.

We need to either iterate on the TS concepts, or iterate on the C++0x concepts. But I, for one, prefer no feature over bad feature, and I much prefer writing sfinae over doing TS concepts (and my first non trivial attempt at them has shown me that I'd still need crazy code to express the constraints that I have). If you want your users to suffer less - use a macro like Range v3's REQUIRES.

--
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.

Jakob Riedle

unread,
Jun 28, 2017, 6:41:01 AM6/28/17
to ISO C++ Standard - Future Proposals


Am Dienstag, 27. Juni 2017 16:01:45 UTC+2 schrieb Michał Dominiak:
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".

Oh sure, gotcha! I understand now, what a concept map is, which I apparently did not previously.

 

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.

But in this case, you exclude everyone from using Concepts, who wants to use concepts as contracts on types!?
The following example shall elaborate on that, If you should see not, why this is the case:

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;
   
}
};

Either you
  1. presume UFCS and the definition of LessThanComparable finds the freestanding operator< (BTW as well as built-in operators for let's say 'int') or
  2. you leave UFCS out, in which case you have to write concept_maps/adaptors for every class/primitive type that implements operators not as member functions (e.g. like Foo).
So either you consider UFCS in some form or you end up with concepts not being able to be used as constracts on types.
From your talk I understand your point on why it is neat to specify Interfaces instead of usage :D, but if you do not presume some sort of UFCS then concepts are once more only a partial solution.
Was that explained properly? I hope, you see my point.


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

Michał Dominiak

unread,
Jun 28, 2017, 7:14:56 AM6/28/17
to std-pr...@isocpp.org
My ultimate idealistic goal would be to have predefined concepts for operators (that'd be used for lookup when an operator is invoked) and then make people migrate to those (to use proper customization points for customization, and to eventually completely stop using ADL for customization points).
 
 
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.

I see ADL as the biggest enemy here; see 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?

Dunno - I don't see the similarity really, concepts define a static set of requirements, while contracts specify invariants dynamically, in a way that's related directly to a position in code. You can see some syntactic parallels between the two (especially when you can do your claim everywhere, and requires everywhere), but they serve purposes that are different enough that I can't see too much of a semantic parallel.
 
 
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.

Ville Voutilainen

unread,
Jun 28, 2017, 7:22:28 AM6/28/17
to ISO C++ Standard - Future Proposals
On 27 June 2017 at 21:53, Michał Dominiak <gri...@griwes.info> wrote:
>> If you had a better idea, you could have been working on it in parallel
>> with Concepts TS. You could have gotten together with people and wrote a
>> proposal with standards wording, forked Clang and implemented it, and proven
>> your point. After all, Concepts Lite was able to do those things. Right now,
>> you are nothing but words, while Concepts TS is a real, live, and useful
>> feature of C++.
>
>
> Yes, splendid. Let's get a terrible feature in because we prefer that over
> nothing. This has never caused any problems for anyone, right?

Where are the papers describing how Concepts are terrible? You've had 6 years
to write them.

> About the only thing I like from the TS is the requires expressions in any
> context and the requires clauses on declarations. Pulling more stops us from
> ever having a truly good feature dealing with this.

I fail to see how what you like or not is something we should take seriously.

> We need to either iterate on the TS concepts, or iterate on the C++0x
> concepts. But I, for one, prefer no feature over bad feature, and I much

Iterating on the C++0x concepts is certainly a great way to waste
everybody's time.

> prefer writing sfinae over doing TS concepts (and my first non trivial
> attempt at them has shown me that I'd still need crazy code to express the
> constraints that I have). If you want your users to suffer less - use a
> macro like Range v3's REQUIRES.

Wow. My attempts have shown me that the code is *MUCH* less crazy than
it is with
SFINAE. 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

Michał Dominiak

unread,
Jun 28, 2017, 7:41:19 AM6/28/17
to ISO C++ Standard - Future Proposals
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.

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).

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.

--
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.

Ville Voutilainen

unread,
Jun 28, 2017, 8:18:52 AM6/28/17
to ISO C++ Standard - Future Proposals
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.

Michał Dominiak

unread,
Jun 28, 2017, 8:36:04 AM6/28/17
to std-pr...@isocpp.org
On Wed, Jun 28, 2017 at 2:18 PM Ville Voutilainen <ville.vo...@gmail.com> wrote:
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.

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.

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?
 

> 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.
 

> 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 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.
 

--
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.

Ville Voutilainen

unread,
Jun 28, 2017, 8:51:16 AM6/28/17
to ISO C++ Standard - Future Proposals
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.

Michał Dominiak

unread,
Jun 28, 2017, 9:09:04 AM6/28/17
to std-pr...@isocpp.org
On Wed, Jun 28, 2017 at 2:51 PM Ville Voutilainen <ville.vo...@gmail.com> wrote:
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".

"I prefer doing X over Y" states preference, not whether I claim X is better than Y. TS concepts are indeed a better way to express the same intent as SFINAE than SFINAE, but I prefer having to do SFINAE over having TS concepts because of how TS concepts being merged into the standard impact future development of related features.
 
And yes, if you
have something
to say about concepts, you should say it in a paper.

Yes, probably.
 

>> > 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?

I've overstated this; I'm sorry. For some reason I was under an impression there's been more papers in the previous years. My bad.
 

>> > 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.

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.

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.)

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.
 

--
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.

Ville Voutilainen

unread,
Jun 28, 2017, 9:20:31 AM6/28/17
to ISO C++ Standard - Future Proposals
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.

Nicol Bolas

unread,
Jun 28, 2017, 9:21:13 AM6/28/17
to ISO C++ Standard - Future Proposals
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.

Michał Dominiak

unread,
Jun 28, 2017, 9:26:46 AM6/28/17
to std-pr...@isocpp.org
On Wed, Jun 28, 2017 at 3:21 PM Nicol Bolas <jmck...@gmail.com> wrote:
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.

The paper I referred to is a late paper for Toronto, that I assume will become public in the post-meeting mailing.
 

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.

Michał Dominiak

unread,
Jun 28, 2017, 9:31:45 AM6/28/17
to std-pr...@isocpp.org
On Wed, Jun 28, 2017 at 3:20 PM Ville Voutilainen <ville.vo...@gmail.com> wrote:
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.

I doubt I'll really reach the authors of the proposal even when I do write a paper, but that's a different issue... :P As I said, right now I'm primarily interested in what the voting part of the committee does in Toronto; I'll treat that as a direction of whether anyone might actually listen. If it appears that there's a sufficient consensus to put the TS into the WP, I'll probably write a different paper that I would've written if no such sufficient consensus is reached.
 

> 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.

Those concerns are probably going to be raised at the meeting in one form or another. I have strong views on this, but I recognize that the process is a democratic one and I won't fall into black despair if the committee decides to follow p0724r0.
 

--
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.

Ville Voutilainen

unread,
Jun 28, 2017, 9:35:16 AM6/28/17
to ISO C++ Standard - Future Proposals
On 28 June 2017 at 16:31, Michał Dominiak <gri...@griwes.info> wrote:
> Those concerns are probably going to be raised at the meeting in one form or
> another. I have strong views on this, but I recognize that the process is a
> democratic one and I won't fall into black despair if the committee decides
> to follow p0724r0.


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. ;)

Michał Dominiak

unread,
Jun 28, 2017, 9:38:20 AM6/28/17
to std-pr...@isocpp.org
On Wed, Jun 28, 2017 at 3:35 PM Ville Voutilainen <ville.vo...@gmail.com> wrote:
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. ;) 

It's approximately democratic in that there's voting taking place :P
 
--
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.

Ville Voutilainen

unread,
Jun 28, 2017, 9:38:34 AM6/28/17
to ISO C++ Standard - Future Proposals
Also, p0724r0 (which, since Jason asked about it, can also be found here:
https://isocpp.org/files/papers/p0724r0.html) is merely suggesting an
as-is merge
to get Concepts one step forward, but it's not suggesting that they be
standardized
as is. I do understand that making the currently-proposed fixes to it
might still not be good
enough for you.

Michał Dominiak

unread,
Jun 28, 2017, 9:40:50 AM6/28/17
to std-pr...@isocpp.org
Oh, good to know it's also publicly available. Yes, I understand that; and yes, while iterating over the TS concepts within the standard WP can make me dislike them less, it's probably not going to make me like 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.

Hyman Rosen

unread,
Jun 28, 2017, 12:07:57 PM6/28/17
to std-pr...@isocpp.org

Ville Voutilainen

unread,
Jun 28, 2017, 12:22:44 PM6/28/17
to ISO C++ Standard - Future Proposals
Maybe, but that still beats the current language, which cannot be used
to write that overload
set without out-of-band trait definitions.

Bryce Glover

unread,
Jul 1, 2017, 9:14:29 PM7/1/17
to Jakob Riedle, std-pr...@isocpp.org
Dear Jakob, 

     Somebody you might want to discuss the opinion you’ve been trying get across in this thread with would be Alisdair Meredith.  Having just recently watched his C++Now 2017 talk ‘C++20 Language Features for a New Library,’ I can remark that he states thoughts along the same lines as yours when transitioning from discussing concepts to discussing contracts (I’d give you a link to the exact point in time during his presentation where he does so, but I can’t exactly recall it at the moment; sorry about that.)  

Hope that helps anyway, 
     Bryce Glover

Jakob Riedle

unread,
Jul 2, 2017, 2:22:05 AM7/2/17
to ISO C++ Standard - Future Proposals, jakob....@gmail.com
Hi Bryce!

nice to know that! I will get in touch with him. Thank you!
If you don't happen to find the spot, I'll watch the whole Presentation, don't worry.

Cheers,
Jakob

PS: A Proposal is already started :)
Reply all
Reply to author
Forward
0 new messages