Complex requirements on constructed types in requires-expression

69 views
Skip to first unread message

Tschijnmo Tschau

unread,
Oct 6, 2016, 6:07:19 PM10/6/16
to SG8 - Concepts
Hi everybody on this group,

I am recently experimenting concepts within a non-trivial project and run into some problems with complex requirement on types constructed from the type constrained by the concept.  For instance, in the following minimized example,

```
template<typename T>

concept bool Example_concept = requires (T t) {

    typename T::A;

    requires requires (T t, typename T::A a) {

        { t + a } -> T;

    };

};

```

From the type T, which is directly constrained by the requirement, we first have the type requirement on the existence of the type T::A.  However, when there are other requirements on T::A in connection with T, it seems to be not possible to introduce another local parameter inside requirement-body, after the the requirement-parameter-list is closed.  So we have the code above, which seem to work in the latest version of g++.  However, although the nested requires-expression solves the problem of introducing new local parameters, the local parameters in the outer requirement expression are all lost, hence have to be repeated in the requirement-parameter-list of the nested.  Could anyone help me if there are better ways this kind of constraint can be specified?  I was thinking it might be convenient if local parameters can be introduced in type requirements [expr.prim.req.type], enabling something like,


```
template<typename T>

concept bool Example_concept = requires (T t) {

    typename T::A (some syntax containing a, like just a);

    { t + a } -> T;

};

```


Or maybe if nested requires-expression could capture the local parameters in the nesting requires-expression, something like,


```
template<typename T>

concept bool Example_concept = requires (T t) {

    typename T::A;

    requires requires (typename T::A a) {

        { t + a } -> T;

    };

};

```


could be equally nice.  Any help with plans or comments about  feature of this style, or suggestions of better alternatives about this problem will be deeply appreciated.



Message has been deleted

Casey Carter

unread,
Oct 6, 2016, 6:17:53 PM10/6/16
to SG8 - Concepts
On Thursday, October 6, 2016 at 3:07:19 PM UTC-7, Tschijnmo Tschau wrote:
Hi everybody on this group,

I am recently experimenting concepts within a non-trivial project and run into some problems with complex requirement on types constructed from the type constrained by the concept.  For instance, in the following minimized example,

```
template<typename T>

concept bool Example_concept = requires (T t) {

    typename T::A;

    requires requires (T t, typename T::A a) {

        { t + a } -> T;

    };

};

```


I would write this as a conjunction of two requires clauses:
```
template<typename T>

concept bool Example_concept =

    requires { typename T::A; }

    && requires (T t, typename T::A a) {

        { t + a } -> T;

    };

```

which is semantically equivalent to:

```
template<typename T>

concept bool Example_concept =

    requires (T t, typename T::A a) {

        { t + a } -> T;

    };

```

since both will be unsatisfied if T::A is not a type, but the first version will (hopefully) produce better error diagnostics.

Tschijnmo Tschau

unread,
Oct 7, 2016, 12:02:23 AM10/7/16
to SG8 - Concepts
Thank you so much for your suggestion!  I have already modified my concepts into the form of

requires {
    ... ... type constraints ... ...
} && requires (
    ... ... a lot of local parameters from all kinds of types
) {
    ... ... other constraints ... ...
}

and things seem to work fine.

Although the local parameters are not repeatedly introduced, I am still kind of thinking that it could be really nice if things, like local parameters and type names, could be added inside the requires-expressions, something like

template<typename T>
concept bool Example = requires {
   typename T::Inside_type a, b;
   { ...expressions of a, b... }
};

which could possibly save a long parameter-declaration-clause.  Or even

template<typename T>
concept bool Example = requires (T t) {
   { ... expression of t... } -> ...some trailing-return-type involving a placeholder U;
   { ... expression of t... } -> ...some trailing-return-type involving a placeholder V;
   requires Another_concept<U, V>;
};

which could save the repetition of the expressions and the use of decltype when requiring `Another_concept`.  Currently it seems that the placeholders are not given any deduced type after the compound requirement is verified.  Their deduced types seem just be thrown.  Could anyone help me if the committee had explored this style of features, or is the committee open to this style of features?  In my exploratory code, I found these two features could make some code a lot more clean and concise.
Reply all
Reply to author
Forward
0 new messages