Document number: N4446
Project: Programming Language C++, Library Evolution Working Group
Reply-to: Agustín Bergé firstname.lastname@example.org
INVOKE related trait
This paper proposes to introduce a new trait to determine whether an
INVOKE expression is well formed.
Starting with C++11, the library introduced the pseudo-macro
INVOKE as a
way to uniformly handle function objects and member pointers as call
expressions. The trait
result_of was made to follow
as well. This left users —who want to follow the precedence set forth by
the standard library— with the correct result type but no direct way of
obtaining such result, and
invoke implementations proliferated.
This was recently rectified by the introduction of
invoke to the working
draft [N4169]. However, there is still one piece of the puzzle missing, and is
the ability to query whether an
INVOKE expression is well formed when
treated as an unevaluated operand. Such functionality is currently present in
the form of C++14 SFINAE-friendly
result_of, albeit in a non user-friendly
way, and it should be made readily available in trait form for the same
invoke was introduced into the library.
The following is an artist depiction of such trait:
This trait is implemented in the wild under different names, and the check for a compatible result type is not always present. This post [call-me-maybe] shows how the implementation of such trait has been both improved and simplified by every new standard.
3. Design questions
The property this trait determines is usually referred to as whether something
is callable with given arguments , a name dating from
INVOKE was introduced. But perhaps callable is not the most
appropriate name, as the standard already defines a number of things by that
20.9.1 [func.def]/3 A callable type is a function object type or a pointer to member.
20.9.1 [func.def]/4 A callable object is an object of a callable type.
These definitions of callable do not represent what the trait would do. Knowing whether some object is a function object or pointer to member is meaningless, as it does not tell whether operating on such an object would be well formed.
The following definition of —proper cased— Callable, introduced
and used only by
std::function, matches exactly what the trait would do:
18.104.22.168 [func.wrap.func]/2 A callable object
Fis Callable for argument types
ArgTypesand return type
Rif the expression
INVOKE(f, declval<ArgTypes>()..., R), considered as an unevaluated operand, is well formed.
The rest of the standard library simply requires
INVOKE expressions being
The ranges proposal [N4128] uses the term invokable instead, for things
that work with
INVOKE, and defines an
3.2 Compatible return types
INVOKE comes in two flavors, the primary
INVOKE(f, t1, t2, ..., tN)
INVOKE(f, t1, t2, ..., tN, R) defined as
INVOKE(f, t1, t2, ..., tN)
implicitly converted to
R. Both flavors can be supported with a defaulted
[Note: This assumes that the resolution for LWG2420 makes
INVOKE(f, t1, t2, ..., tN, void) discard the return type. -end note]
However, if only one of those flavors would be supported there would be no missing functionality, only more work for the user.
4. Proposed Wording
This wording is relative to [N4296].
Change 20.10.2 [meta.type.synop], header
<type_traits> synopsis, as
// 22.214.171.124, type properties:
Change 126.96.36.199 [meta.unary.prop], Table 49 — Type property predicates, add a new row with the following contents:
INVOKE(declval<Fn>(), declval<ArgTypes>()..., R)is well formed when treated as an unevaluated operand.
Fnand all types in the parameter pack
ArgTypesshall be complete types, (possibly cv-qualified)
void, or arrays of unknown bound.
[N4296] ISO/IEC JTC1 SC22 WG21, Programming Languages - C++, working draft, November 2014 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf
[call-me-maybe] True Story: Call Me Maybe - Tales of C++ http://talesofcpp.fusionfenix.com/post-11/true-story-call-me-maybe
[N4169] A proposal to add invoke function template (Revision 1) - Tomasz Kaminski http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4169.html
[N4128] Ranges for the Standard Library, Revision 1 - Eric Niebler, Sean Parent, Andrew Sutton http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4128.html