is_constructible underspecified when applied to a function type
Richard Smith

Created on 2015-11-14.00:00:00 last changed 83 months ago


Date: 2016-02-07.20:24:45

Proposed resolution:

This wording is relative to N4567.

  1. Change [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.
Date: 2016-02-07.20:24:45

[ 2016-02, Issues Telecon ]

P0; move to Tentatively Ready.

Date: 2015-11-14.00:00:00

What is is_constructible<void()>::value? Per [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 [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.


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.

Date User Action Args
2017-07-30 20:15:43adminsetstatus: wp -> c++17
2016-03-07 04:11:48adminsetstatus: ready -> wp
2016-02-07 20:24:45adminsetmessages: + msg7959
2016-02-07 20:24:45adminsetstatus: new -> ready
2015-12-10 20:28:22adminsetmessages: + msg7636
2015-11-14 00:00:00admincreate