Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Incomplete type syntax and namespaces in C++

Tags:

c++

In the following snippet of C++ code, I have declared a function type using the incomplete type syntax inside a namespace s, but the inner struct unknown_type have namespace scope and so the full qualified name of the argument is taken as ::s::unknown_type.

So this works:

namespace s {
    using callback = void(struct unknown_type);
    struct unknown_type {};
}

void f(s::unknown_type) {}

int main()
{
    s::callback* cb = f;
    (void)cb;
    return 0;
}

but this doesn't:

namespace s {
    using callback = void(struct unknown_type);
}

struct unknown_type {};
void f(unknown_type) {}

int main()
{
    s::callback* cb = f;
    (void)cb;
    return 0;
}

I know that I can just properly forward declare the type as usual, but I'm curious about this syntax. I have tried with using callback = void(struct ::unknown_typee) but it doesn't work. Is there a way to forward declare a type using the incomplete type syntax specifying the right expected namespace?

like image 387
Peregring-lk Avatar asked Sep 01 '25 03:09

Peregring-lk


1 Answers

Is there a way to forward declare a type using the incomplete type syntax specifying the right expected namespace?

Simply put, no, there is no way. The way this is specified in the latest C++ standard (c++23) is probably clearest.

[basic.lookup.elab]

2 If the terminal name of the elaborated-type-specifier is a qualified name, lookup for it is type-only. If the name lookup does not find a previously declared type-name, the elaborated-type-specifier is ill-formed.

Lookup being "type-only" is (very roughly speaking) standard verbiage for doing lookup that should only find types (in other contexts, types may be hidden). Unlike unqualified names, this passage explicitly tells us that if we form an elaborate-type-specifier with a fully qualified name, it must refer to a class whose declaration is already visible at this point.

It is then followed by an (albeit non-normative) example that applies to your question:

[basic.lookup.elab]

3 ...

struct Data {
  // ...
  friend struct ::Glob;         // error: Glob is not declared, cannot introduce a qualified type ([dcl.type.elab])
  friend struct Glob;           // OK, refers to (as yet) undeclared Glob at global scope.
  /* ... */
};
like image 158
StoryTeller - Unslander Monica Avatar answered Sep 02 '25 16:09

StoryTeller - Unslander Monica