5

Consider something like this:

class A;

std::function<A(A)> f;

This is clearly something you want to do in your program. Any major compiler accepts that without problems.

My question is: is it technically allowed by the standard?

If I see correctly, the section

20.5.4.8 Other functions

prohibits use of template parameters of incomplete type at instantiation, unless otherwise specified (and not only for containers).

In the section about std::function or <functional> I see no reference to allowing this.

Does somebody know where and if this is explicitly written in the standard?

FilippoL
  • 160
  • 7
  • From the "latest" version of the standard: *"[...] the effects are undefined [...]"*. [res.on.functions](http://eel.is/c++draft/res.on.functions). So I think there are no requirements on the implementation, it may accept that – BiagioF Jul 19 '19 at 11:39

1 Answers1

2

This is covered by the library catch-all [res.on.functions]/2

In particular, the effects are undefined in the following cases: [...]

  • if an incomplete type ([basic.types]) is used as a template argument when instantiating a template component or evaluating a concept, unless specifically allowed for that component.

Since nothing in [func.wrap.func] overrides this, it is undefined behavior to have an incomplete function type.

As an example of what an you would need to see in [func.wrap.func] lets look at [unique.ptr]/4

[...] The template parameter T of unique_­ptr may be an incomplete type.

Here it explicitly states that an incomplete type is allowed. We would need something like that in [func.wrap.func] and we don't, so we fall back to [res.on.functions]/2 and it being undefined behavior.

Community
  • 1
  • 1
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • This was my suspicion. Should all major compilers warn (e.g. GCC with pedantic), or should it be allowed in the standard? I see a minor defect here, either from compilers or from the standard. (Along the lines of http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4371.html) – FilippoL Jul 19 '19 at 13:25
  • @FilippoL Well, in case of undefined behavior is not required to emit a warning – BiagioF Jul 19 '19 at 13:34
  • @FilippoL Per [this](https://timsong-cpp.github.io/cppwp/intro.compliance#1) the compiler is not required to diagnose undefined behavior. – NathanOliver Jul 19 '19 at 13:36
  • @NathanOliver are we sure this is an actual UB? Doesn't the standard let the compiler the choice to accept the code as valid (without UB)? – BiagioF Jul 19 '19 at 13:36
  • @BiagioFesta [res.on.functions]/2 says **the effects are undefined** – NathanOliver Jul 19 '19 at 13:37
  • What about this sentence: `A callable type F is Lvalue-Callable for argument types ArgTypes and return type R if the expression INVOKE(declval(), declval()...), considered as an unevaluated operand, is well-formed` And `[expr.context]`: `In some contexts, unevaluated operands appear [...] An unevaluated operand is not evaluated. [ Note: In an unevaluated operand, a non-static class member may be named ([expr.prim.id]) and naming of objects or functions does not, by itself, require that a definition be provided ([basic.def.odr]).` – FilippoL Jul 19 '19 at 13:38
  • @FilippoL That doesn't help. It explicitly states *is well-formed* and it is not well-formed per [res.on.functions]/2. There needs to be an explicit *incomplete type is allowed*, and there isn't, so it isnt. – NathanOliver Jul 19 '19 at 13:43