2560. is_constructible underspecified when applied to a function type

Section: 23.15.4.3 [meta.unary.prop] Status: C++17 Submitter: Richard Smith Opened: 2015-11-14 Last modified: 2017-07-30

Priority: 0

View other active issues in [meta.unary.prop].

View all other issues in [meta.unary.prop].

View all issues with C++17 status.

Discussion:

What is is_constructible<void()>::value? Per 23.15.4.3 [meta.unary.prop] p8:

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:

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

[Note: These tokens are never interpreted as a function declaration. — end note]

The problem here is that substituting in T as a function type doesn't give a variable definition that's not well-formed (by 3.29 [defns.well.formed], well-formed means that it doesn't violate any syntactic or diagnosable semantic rules, and it does not). Instead, it gives a logical absurdity: this wording forces us to imagine a variable of function type, which contradicts the definition of "variable" in 3/6, but does so without violating any diagnosable language rule. So presumably the result must be undefined behavior.

It seems that we need an explicit rule requiring T to be an object or reference type.

Daniel:

As one of the authors of N3142 I would like to express that at least according to my mental model the intention for this trait was to be well-defined for T being a function type with the result of false regardless of what the other type arguments are. It would seem like a very unfortunate and unnecessary complication to keep the result as being undefined. First, this result value is symmetric to the result of is_destructible<T>::value (where the word covers function types explicitly). Second, if such a resolution would be applied to the working paper, it wouldn't break existing implementations. I have tested clang 3.8.0, gcc 5.x until gcc 6.0, and Visual Studio 2015, all of these implementations evaluate is_constructible<void()>::value to false.

[2016-02, Issues Telecon]

P0; move to Tentatively Ready.

Proposed resolution:

This wording is relative to N4567.

  1. Change 23.15.4.3 [meta.unary.prop], Table 49 — "Type property predicates", as indicated:

    Table 49 — Type property predicates
    Template Condition Preconditions
    template <class T, class... Args>
    struct is_constructible;
    For a function type T,
    is_constructible<T, Args...>::value
    is false, otherwise
    see below
    T and all types in the
    parameter pack Args shall
    be complete types,
    (possibly cv-qualified)
    void, or arrays of
    unknown bound.