简体   繁体   中英

C++ Concepts with multiple template arguments

Bjarne Stroustrup recently published a report on C++ Concepts where he mentions something that seemed surprising to me. The example (in Section 7.1) uses "shorthand template notation" and essentially goes like this:

void foo1(auto x,auto y);                // x and y may have different types  (1)
void foo2(SomeConcept x,SomeConcept y);  // x and y must have the same type   (2)

To me personally, this seems very counter-intuitive; in fact, I would expect foo2 to accept values x,y of different types as long as the respective types satisfy SomeConcept. Note that the programmer can always explicitly specify his intent by writing one of the following:

template <SomeConcept T> void foo2(T x, T y);                   // (3)
template <SomeConcept T1,SomeConcept T2> void foo2(T1 x,T2 y);  // (4)

Intuitively, I would expect the shorthand notation from (2) to be equivalent to (4) and thus be more consistent with the meaning of the unconstrained template (1). Can somebody shed light on the matter and explain the rationale behind this design decsision?

Some remarks:

  • afaik, generic lambdas (in C++14) already allow a syntax similar to (1). Hence, consistency dictates that (1) should accept input variables with different types, since generic lambdas do that.
  • Stroustrup mentions the classical "iterator pair" in the context of such templates. However, I believe that this is a fairly weak argument since (i) this is just one use-case and (ii) afaik, C++17 introduces (iterator, sentinel) pairs, which forces generic code to use two different types anyway.

The earliest paper I could find that mentions the terse syntax in the context of the current Concepts proposal is N3580 , which in §6.2.2 provides this rationale:

What if we need two argument types of the same concept? Consider

 void sort(Ran p, Ran q); 

For this to make sense, p and q must be of the same type, and that is the rule. By default, if you use the same constrained parameter name for two arguments, the types of those arguments must be the same. We chose to make repeated use of a constrained parameter name imply “same type” because that (in most environments) is the most common case and the aim here is to optimize for terse notation of the simplest case. Also, a constrained parameter is the name of a type, and having two type names refer to different types in the same scope would cause chaos.

Tony van Eerd and Boton Ballo have a proposal to change this meaning: P0464 . The paper provides two arguments in support of the current meanings, one similar to the one Sutton et al make, and one orthogonal:

Frequency of use
It can be argued that you don't often want a function that takes two arguments of potentially different types satisfying the same concept without having an additional relationship between the two types.

Interaction with definition checking
It can also be argued that this change will encourage template authors to write under-constrained templates, because they will opt to use the terse R foo(ConceptName, ConceptName); form even in cases where in there should be an additional constraint on the parameter types. A proliferation of under-constrained templates will make the introduction of definition checking harder, because an under-constrained template will not pass definition checking.


I'm not familiar with any other argument in favor of the current syntax, but if you are, feel free to email Tony and Botond for inclusion into their paper.

Just a quick update for those who tagged this question or find it on Google.

The issue discussed here was resolved---apparently silently---before the C++ standards meeting in Jacksonville, March 2018. To quote from Botond's trip report :

As an aside, one topic that seems to have been settled without much discussion was the question of independent resolution vs. consistent resolution ; that is, if you have two uses of the same concept in an AFT (as in void foo(Number, Number); ), are they required to be the same concrete type (“consistent”), or two potentially different types that both model the concept (“independent”). The Concepts TS has consistent resolution, but many people prefer independent resolution. I co-authored a paper arguing for independent resolution a while back; that sentiment was subsequently reinforced by another paper, and also in a section of the Sortable{S} proposal. Somewhat to my amusement, the topic was never actually formally discussed and voted on; the idea of independent resolution just seemed to slowly, over time, win people over, such that by this meeting, it was kind of treated as a done deal, that any AFT proposal going into C++20 will, in fact, have independent resolution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM