Given:
#include
class world_building_gun;
class tile_bounding_box;
typedef std::function
I'd say no. From 20.8.11.2 Class template function [func.wrap.func], we have:
3 The
functionclass template is a call wrapper (20.8.1) whose call signature (20.8.1) isR(ArgTypes...).
In 20.8.1 Definitions [func.def ], we get the following definitions as to what constitutes a call wrapper type, a call wrapper and a call signature:
2 A call signature is the name of a return type followed by a parenthesized comma-separated list of zero or more argument types.
5 A call wrapper type is a type that holds a callable object and supports a call operation that forwards to that object.
6 A call wrapper is an object of a call wrapper type.
Notice how paragraph 2 doesn't mention completeness of types.
To cut a story short (a lot of definitions are involved), the meaning of 'callable object' here means either a functor (the familiar notion, i.e. something that can be used like a function) or a pointer-to-member. Furthermore the Standard also describe the Callable concept in 20.8.11.2 paragraph 2:
A callable object
fof typeFis Callable for argument typesArgTypesand return typeRif the expression INVOKE(f, declval, considered as an unevaluated operand (Clause 5), is well formed (20.8.2).()..., R)
(The INVOKE bit is an imaginary function that the Standard uses to define how functors and pointers to members are, well, invoked.)
What I think is the most important conclusion from that is the following requirement:
R(A...), then R and A... are complete (or possibly R is void) by virtue of the INVOKE expression (i.e. otherwise it would not be well-formed, notice the use of declval()... )My argument now rests on '[the] call operation that forwards to that object' in the definition of call wrappers, which I think is intentionally left vague so as to not be overly restrictive. In the case of std::function where some incomplete types are involved in Sig then we could define this operation as being 'first complete the types, then treat std::function as a callable object type of call signature Sig'.
Given that, here are the key points of my argument:
std::function is not described as being a callable object or as being Callable for any signaturestd::function is done in terms of INVOKE (20.8.11.2.4 function invocation [func.wrap.func.inv])std::function from a callable object is in terms of Callable with the call signature of std::function (20.8.11.2.1 function construct/copy/destroy [func.wrap.func.con] paragraph 7)target member of std::function is in terms of Callable with the call signature of std::function (20.8.11.2.5 function target access [func.wrap.func.targ])std::function are not described in terms of callable object(*) , Callable, INVOKE or otherwise require that the call signature of std::function involve complete types(*) except in the case of one constructor where the description contains "shall not throw exceptions if f’s target is a callable object passed via reference_wrapper or a function pointer". I think in the context it's clear that this doesn't affect the argument. For what it's worth this constructor is not involved in the snippet of the OP.
So I'd say unless you do use one of those operations that indirectly require the signature to involve complete types, you're good to go.
It's all well and good to analyze what the Standard prescribes but it's also important to consider what is the intent of the Standard. In this case I think it is very much desirable and expected that std::function does not require that the types of the call signature be complete. Consider the following:
// in a_fwd.hpp
struct incomplete;
using callback_type = std::function;
callback_type make_callback();
// in b.hpp; depends on a_fwd.hpp
#include "a_fwd.hpp"
void eat_callback(callback_type);
Then without the requirement an unrelated TU, let's call it C, that is a client of B can do:
// in c.cpp
#include "b.hpp"
// somewhere in e.g. a function body
eat_callback(make_callback());
This is type-safe and minimizes the coupling since only translation unit B need to know about the details of translation unit A.
Furthermore both Boost.Function and libstdc++ have demonstrated that it is possible to implement std::function without such a requirement.