Title
is_* traits for binding operations can't be meaningfully specialized
Status
c++14
Section
[func.bind.isbind]
Submitter
Sean Hunt

Created on 2010-07-19.00:00:00 last changed 123 months ago

Messages

Date: 2011-08-16.10:45:53

Proposed resolution:

This wording is relative to the FDIS.

  1. Change [func.bind.isbind] to:

    namespace std {
      template<class T> struct is_bind_expression; // see below
        : integral_constant<bool, see below> { };
    }
    

    -1- is_bind_expression can be used to detect function objects generated by bind. bind uses is_bind_expression to detect subexpressions. Users may specialize this template to indicate that a type should be treated as a subexpression in a bind call.

    -2- If T is a type returned from bind, is_bind_expression<T> shall be publicly derived from integral_constant<bool, true>, otherwise from integral_constant<bool, false>Instantiations of the is_bind_expression template shall meet the UnaryTypeTrait requirements ([meta.rqmts]). The implementation shall provide a definition that has a BaseCharacteristic of true_type if T is a type returned from bind, otherwise it shall have a BaseCharacteristic of false_type. A program may specialize this template for a user-defined type T to have a BaseCharacteristic of true_type to indicate that T should be treated as a subexpression in a bind call..

    -3- is_placeholder can be used to detect the standard placeholders _1, _2, and so on. bind uses is_placeholder to detect placeholders. Users may specialize this template to indicate a placeholder type.

    -4- If T is the type of std::placeholders::_J, is_placeholder<T> shall be publicly derived from integral_constant<int, J>, otherwise from integral_constant<int, 0>.

  2. Insert a new sub-clause immediately following sub-clause [func.bind.isbind], the suggested sub-clause tag is [func.bind.isplace]:

    20.8.9.1.? Class template is_placeholder [func.bind.isplace]

    namespace std {
      template<class T> struct is_placeholder; // see below
    }
    

    -?- is_placeholder can be used to detect the standard placeholders _1, _2, and so on. bind uses is_placeholder to detect placeholders.

    -?- Instantiations of the is_placeholder template shall meet the UnaryTypeTrait requirements ([meta.rqmts]). The implementation shall provide a definition that has a BaseCharacteristic of integral_constant<int, J> if T is the type of std::placeholders::_J, otherwise it shall have a BaseCharacteristic of integral_constant<int, 0>. A program may specialize this template for a user-defined type T to have a BaseCharacteristic of integral_constant<int, N> with N > 0 to indicate that T should be treated as a placeholder type.

Date: 2011-08-16.10:45:53

[ Bloomington, 2011 ]

Move to Ready

Date: 2011-05-18.00:00:00

[ 2011-05-18 Daniel comments and provides some refinements to the P/R ]

Both bind-related type traits should take advantage of the UnaryTypeTrait requirements. Additionally, the updated wording does not imply that the implementation provides several specializations. Wording was used similar to the specification of the uses_allocator type trait (which unfortunately is not expressed in terms of BinaryTypeTrait requirements).

Date: 2011-05-13.00:00:00

[ 2011-05-13 Jonathan Wakely comments and provides proposed wording ]

The requirements are that is_bind_expression<T>::value is true when T is a type returned from bind, false for any other type, except when there's a specialization involving a user-defined type (N.B. [namespace.std] means we don't need to say e.g. is_bind_expression<string> is false.)

The obvious way to meet the requirements is for the primary template to derive from integral_constant<bool, false> and for implementations to provide specializations for the unspecified types returned from bind. User-defined specializations can do whatever they like, as long as is_bind_expression::value is sane. There's no reason to forbid users from defining is_bind_expression<user_defined_type>::value=false if that's what they want to do.

Similar reasoning applies to is_placeholder, but a further issue is that [func.bind.isbind] contains wording for is_placeholder but contains no definition of it and the sub-clause name only refers to is_bind_expression. The wording below proposes splitting paragraphs 3 and 4 of [func.bind.isbind] into a new sub-clause covering is_placeholder.

If the template specializations added by the proposed wording are too vague then they could be preceded by "for exposition only" comments

Date: 2011-08-16.10:45:53

[ 2010 Batavia (post meeting session) ]

Alisdair recognises this is clearly a bug introduced by some wording he wrote, the sole purpose of this metafunction is as a customization point for users to write their own bind-expression types that participate in the standard library bind protocol. The consensus was that this should be fixed in Madrid, moved to Open.

Date: 2010-07-19.00:00:00

[func.bind.isbind] says for is_bind_expression:

Users may specialize this template to indicate that a type should be treated as a subexpression in a bind call.

But it also says:

If T is a type returned from bind, is_bind_expression<T> shall be publicly derived from integral_constant<bool, true>, otherwise from integral_constant<bool, false>.

This means that while the user is free to specialize, any specialization would have to be false to avoid violating the second requirement. A similar problem exists for is_placeholder.

History
Date User Action Args
2014-02-20 13:20:35adminsetstatus: wp -> c++14
2012-02-12 18:36:43adminsetstatus: voting -> wp
2012-02-09 04:07:48adminsetstatus: ready -> voting
2011-08-16 10:45:53adminsetmessages: + msg5832
2011-08-16 10:45:53adminsetmessages: + msg5831
2011-08-16 10:45:53adminsetmessages: + msg5830
2011-08-16 10:45:53adminsetmessages: + msg5829
2011-08-16 10:45:53adminsetstatus: open -> ready
2011-05-16 22:34:51adminsetmessages: + msg5774
2010-11-16 14:47:55adminsetstatus: new -> open
2010-07-19 00:00:00admincreate