https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116640

            Bug ID: 116640
           Summary: Inconsistent compiler rules when using private types
                    as default template parameters
           Product: gcc
           Version: 14.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: joshua.maiche at gmail dot com
  Target Milestone: ---

Created attachment 59071
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=59071&action=edit
main source file

(Also tested on godbolt trunk)

Version:
gcc version 14.0.1 20240412 (experimental) [master r14-9935-g67e1433a94f]

System:
Ubuntu 24.04 LTS

Command:
gcc main.cpp

Source:
---
struct Outer {
private:
    struct PrivateStruct;
public:
    template <typename = PrivateStruct>
    struct Inner1 {};

    template <typename SelfType = Outer, typename = typename
SelfType::PrivateStruct>
    struct Inner2 {};
};

Outer::Inner1<> obj1{}; // Compiles fine.
Outer::Inner2<> obj2{}; // Fails to compile due to private access.
---

Output:
---
main.cpp:13:8: error: ‘struct Outer::PrivateStruct’ is private within this
context
   13 | Outer::Inner2<> obj2{}; // Fails to compile due to private access.
      |        ^~~~~~~~
main.cpp:3:12: note: declared private here
    3 |     struct PrivateStruct;
      |            ^~~~~~~~~~~~~
---

The C++ compiler seems to have inconsistent rules when using private types in a
member function template.

I could see why private types would be accepted as default template parameters,
since they're being declared in a member of a struct, so that could have access
to privates.

I could also see why private types would be rejected as default template
parameters, since they're being evaluated at the point where the template is
being called, which could be considered "outside the struct"

However, it seems inconsistent to have it where private types are accepted as
default parameters (Inner1), but not as a default parameter dependent on a
previous parameter (Inner2).

For comparison, Clang and MSVC accept both Inner1 and Inner2.

Reply via email to