incomplete class usage with auto in template class
Asked Answered
H

1

10

Is the following code well formed ?

class B;

template<class T>
class A
{
    B do_f() const;
    friend auto f(A const& a) {return a.do_f();} // #1
};

class B{};

template <class T>
B A<T>::do_f() const { return B{};}

int main()
{
    A<double> a;
    f(a);
}

If I change auto in #1 by B, I got incomplete type error message.

Compile with auto for gcc/clang Demo

Fail with B Demo

Huneycutt answered 10/10, 2018 at 23:34 Comment(3)
Is this simplified version the same issue? godbolt.org/z/9V4fx7 Note: gcc compiles; clang report an error.Heshum
@RichardCritten: Not sure, your function is template, whereas mine is a friend function of class template.Huneycutt
@RichardCritten, also, Jarod42 code works with gcc and clang.Alveraalverez
G
8

[dcl.fct.def.general]/2:

The type of a parameter or the return type for a function definition shall not be an incomplete or abstract (possibly cv-qualified) class type in the context of the function definition unless the function is deleted ([dcl.fct.def.delete]).

But [dcl.spec.auto]/10:

Return type deduction for a function template with a placeholder in its declared type occurs when the definition is instantiated even if the function body contains a return statement with a non-type-dependent operand.

So with B, it's ill-formed by the first rule. But with auto, deduction doesn't take place until the function is instantiated... by which point the type is complete, so it's fine.

Note that the first rule only applies to the definition, which is why do_f() is okay. You can have declarations which return incomplete types.


The above wording technically doesn't apply to this case. We don't have a function template. But the intent is for it to apply to any kind of templated thing. There's a PR to editorially fix this from:

Return type deduction for a function template with a placeholder [...]

To:

Return type deduction for a templated entity that is a function or function template with a placeholder in its

Which does apply here.

Garrard answered 10/10, 2018 at 23:52 Comment(6)
f is not a function template here(friend function of class template) though, but I suppose it is the same.Huneycutt
@Huneycutt Yeah, that's probably a wording issue.Garrard
Does this mean that without auto (C++98) it is not possible to make it work?Alveraalverez
@Alveraalverez Defining a non-member friend inline? Nope.Garrard
@Huneycutt github.com/cplusplus/draft/pull/2350, fixed editoriallyGarrard
With the years I found compilers (nvcc, intel) for which auto friend will choke SFINAE (the function is not detected). That is one problem of auto friends. I suppose it is not standard. I think this happens when the compiler cannot deduce auto in the "first pass".Alveraalverez

© 2022 - 2024 — McMap. All rights reserved.