This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Open status.

### 2290. Top-level "SFINAE"-based constraints should get a separate definition in Clause 17

Section: 20.15 [meta] Status: Open Submitter: Daniel Krügler Opened: 2013-09-02 Last modified: 2016-01-28

Priority: 3

View other active issues in [meta].

View all other issues in [meta].

View all issues with Open status.

Discussion:

The current library specification uses at several places wording that is intended to refer to core language template deduction failure at the top-level of expressions (aka "SFINAE"), for example:

> The expression `declval<T>() = declval<U>()` is well-formed when treated as an unevaluated operand (Clause 5). Access checking is performed as if in a context unrelated to `T` and `U`. Only the validity of the immediate context of the assignment expression is considered. [Note: The compilation of the expression can result in side effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on. Such side effects are not in the "immediate context" and can result in the program being ill-formed. — end note]

Similar wording can be found in the specification of `result_of`, `is_constructible`, and `is_convertible`, being added to resolve an NB comment by LWG 1390 and 1391 through N3142.

This wording is necessary to limit speculative compilations needed to implement these traits, but it is also lengthy and repetitive.

[2014-05-19, Daniel suggests a descriptive term]

constrictedly well-formed expression:

An expression e depending on a set of types `A1`, ..., `An` which is well-formed when treated as an unevaluated operand (Clause 5). Access checking is performed as if in a context unrelated to `A1`, ..., `An`. Only the validity of the immediate context of e is considered. [Note: The compilation of the expression can result in side effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on. Such side effects are not in the "immediate context" and can result in the program being ill-formed. — end note]

[2014-05-20, Richard and Jonathan suggest better terms]

Richard suggested "locally well-formed"

Jonathan suggested "contextually well-formed" and then "The expression ... is valid in a contrived argument deduction context"

[2014-06-07, Daniel comments and improves wording]

The 2014-05-19 suggestion did only apply to expressions, but there are two important examples that are not expressions, but instead are involving an object definition (`std::is_constructible`) and a function definition (`std::is_convertible`), respectively, instead. Therefore I suggest to rephrase the usage of "expression" into "program construct" in the definition of Jonathan's suggestion of "valid in a contrived argument deduction context".

I would like to point out that given the new definition of "valid in a contrived argument deduction context", there are several other places of the Library specification that could take advantage of this wording to improve the existing specification, such as 20.14.17.3 [func.wrap.func] p2, most functions in 20.10.8.3 [allocator.traits.members], and the `**Insertable`, `EmplaceConstructible`, and `Erasable` definitions in 22.2.1 [container.requirements.general], but given that these are not fully described in terms of the aforementioned wording yet, I would recommend to fix them by a separate issue once the committee has agreed on following the suggestion presented by this issue.

[2015-05-05 Lenexa: Move to Open]

...

MC: I think we like the direction but it isn't quite right: it needs some work

JW: I'm prepared to volunteer to move that further, hopefully with the help of Daniel

Roger Orr: should this be Core wording because it doesn't really have anything to do with libraries - the term could then just be used here

AM: Core has nothing to deal with that, though

HT: it seems there is nothing to imply that allows dropping out with an error - maybe that's a separate issue

MC: I'm not getting what you are getting at: could you write an issue? - any objection to move to Open?

...

Proposed resolution:

This wording is relative to N3936.

1. Add the following new definition to [definitions] as indicated:

   valid in a contrived argument deduction context [defns.valid.contr.context]

   A program construct c depending on a set of types `A1`, ..., `An`, and treated as an unevaluated operand (Clause 5) when c is an expression, which is well-formed. Access checking is performed as if in a context unrelated to `A1`, ..., `An`. Only the validity of the immediate context (13.10.3 [temp.deduct]) of c is considered. [Note: The compilation of c can result in side effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on. Such side effects are not in the "immediate context" and can result in the program being ill-formed. — end note].

2. Change Table 49 ("Type property predicates") as indicated:

   > Table 49 — Type property predicates
   > Template | Condition | Preconditions
   > --- | --- | ---
   > `…`
   > `template <class T, class U> struct is_assignable;` | The expression `declval<T>() = declval<U>()` is valid in a contrived argument deduction context ([defns.valid.contr.context]) for types `T` and `U`. well-formed when treated as an unevaluated operand (Clause 5). Access checking is performed as if in a context unrelated to `T` and `U`. Only the validity of the immediate context of the assignment expression is considered. [Note: The compilation of the expression can result in side effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on. Such side effects are not in the "immediate context" and can result in the program being ill-formed. — end note] | […]
   > `…`

3. Change 20.15.5.4 [meta.unary.prop] p7 as indicated:

   > -7- Given the following function prototype:

   > >     template <class T>
   > >       add_rvalue_reference_t<T> create() noexcept;

   > the predicate condition for a template specialization `is_constructible<T, Args...>` shall be satisfied if and only if the following variable definition would be well-formed for some invented variable `t` would be valid in a contrived argument deduction context ([defns.valid.contr.context]) for types `T` and `Args...`:

   > >     T t(create<Args>()...);

   > [Note: These tokens are never interpreted as a function declaration. — end note] Access checking is performed as if in a context unrelated to `T` and any of the `Args`. Only the validity of the immediate context of the variable initialization is considered. [Note: The evaluation of the initialization can result in side effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on. Such side effects are not in the "immediate context" and can result in the program being ill-formed. — end note]

4. Change Table 57 ("Other transformations") as indicated:

   > Table 57 — Other transformations
   > Template | Condition | Comments
   > --- | --- | ---
   > `…`
   > `template <class Fn, class... ArgTypes> struct result_of<Fn(ArgTypes...)>;` | […] | If the expression `INVOKE(declval<Fn>(), declval<ArgTypes>()...)` is valid in a contrived argument deduction context ([defns.valid.contr.context]) for types `Fn` and `ArgTypes...` well formed when treated as an unevaluated operand (Clause 5), the member typedef type shall name the type `decltype(INVOKE(declval<Fn>(), declval<ArgTypes>()...))`; otherwise, there shall be no member type. Access checking is performed as if in a context unrelated to `Fn` and `ArgTypes`. Only the validity of the immediate context of the expression is considered. [Note: The compilation of the expression can result in side effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on. Such side effects are not in the "immediate context" and can result in the program being ill-formed. — end note]
   > `…`

5. Change 20.15.7 [meta.rel] p4 as indicated:

   > -4- Given the following function prototype:

   > >     template <class T>
   > >       add_rvalue_reference_t<T> create() noexcept;

   > the predicate condition for a template specialization `is_convertible<From, To>` shall be satisfied if and only if the return expression in the following code would be well-formed valid in a contrived argument deduction context ([defns.valid.contr.context]) for types `To` and `From`, including any implicit conversions to the return type of the function:

   > >     To test() {
   > >       return create<From>();
   > >     }

   > [Note: This requirement gives well defined results for reference types, `void` types, array types, and function types. — end note] Access checking is performed as if in a context unrelated to `To` and `From`. Only the validity of the immediate context of the expression of the return-statement (including conversions to the return type) is considered. [Note: The evaluation of the conversion can result in side effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on. Such side effects are not in the "immediate context" and can result in the program being ill-formed. — end note]