C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Translation-unit-local functions that access private class fields

From: Rhidian De Wit <rhidiandewit_at_[hidden]>
Date: Mon, 27 Apr 2026 11:27:54 +0200
This proposal from 2013 looks extremely interesting, I’ve also had this
need and thought very often that I needed a way to define private helper
methods without cluttering the header file.

Would love to see where this proposal goes, and if it’s still active? From
what I can tell it seems to not be pursued any longer, but I think it’s a
wonderful idea.

Rhidian De Wit
Software Engineer - Barco


Op ma 27 apr 2026 om 10:49 schreef Jonathan Wakely via Std-Proposals <
std-proposals_at_[hidden]>

>
>
> On Mon, 27 Apr 2026, 08:21 André Offringa via Std-Proposals, <
> std-proposals_at_[hidden]> wrote:
>
>> Hi Steve,
>>
>> Thanks for the feedback. You're suggesting helper friend classes as an
>> alternative, but there are some issues with a helper friend class to enable
>> translation-unit-local functions. First of all, to make the functions
>> translation-unit-local, it must be placed in an anonymous namespace. To do
>> this, it must be done so before the befriending, so something like this:
>>
>> == header file ==
>>
>> namespace {
>> struct FooFriend;
>> }
>>
>> class Foo {
>> int a;
>> friend FooFriend;
>> };
>>
>> == cpp file ==
>>
>> namespace {
>> struct FooFriend {
>> static void SetA(Foo& foo) {
>> foo.a = 3;
>> }
>> };
>> }
>>
>> I think this is an awkward construct. The Google C++ style explicitly
>> forbids this, as it doesn't allow unnamed namespaces in header files.
>>
> It breaks the ODR. The friend declaration refers to a different FooFriend
> in each translation unit.
>
> So the FooFriend solution doesn't mix well with the desire to have
> internal linkage for all the helpers.
>
>
>
> The SetA() function is also now publicly available, and even though that
>> is limited to a single translation unit, it is still easy to accidentally
>> break a class invariant in this way. The classname of FooFriend is leaked
>> out of the scope of the unit file (style guides often mandate to put it in
>> yet another subnamespace like 'details' in that case). Finally, the syntax
>> of the call and use of private variables is more verbose. Compare it to:
>>
>> == header file ==
>>
>> class Foo {
>> int a;
>> };
>>
>> == cpp file ==
>>
>> private Foo::SetA() {
>> a = 3;
>> }
>>
>>
>> So, while there are alternatives for private functions, I don't think the
>> friend classes are really a solution for the issue that the proposal tries
>> to solve.
>>
>> Kind regards,
>> André
>> On 4/26/26 11:05 PM, Steve Weinrich via Std-Proposals wrote:
>>
>> This is purely subjective, but I don't find that a single line, "friend
>> class Helper;" is clutter. It can be put at the very bottom of the class.
>> It gives Helper full access for whatever purpose. No committee required!
>>
>> Cheers,
>> Steve
>>
>> On Sun, Apr 26, 2026, 00:17 André Offringa via Std-Proposals <
>> std-proposals_at_[hidden]> wrote:
>>
>>> On 4/25/26 10:56 PM, Steve Weinrich via Std-Proposals wrote:
>>>
>>> I may have missed something, but one can declare:
>>>
>>> class Foo
>>> {
>>> friend class Helper;
>>>
>>> friend void FooHelper (Foo *);
>>> };
>>>
>>> Both the class Helper and the function FooHelper() can access all
>>> private members of Foo. Thus, only the names and/or the function signature
>>> is declared in the interface.
>>>
>>>
>>> What I'm trying to solve:
>>>
>>> - Wen using friend declarations, these clutters the class with
>>> implementation details that do not affect the layout of the class.
>>>
>>> - For FooHelper(), it would require the return and parameters types to
>>> be available at the place of the friend declaration, creating extra
>>> dependencies. Your example takes only Foo*, but I think it's common for a
>>> helper function to use other parameters (and/or have a return value), which
>>> causes the dependencies.
>>> Regards,
>>> André
>>>
>>>
>>>
>>> On Sat, Apr 25, 2026, 14:46 André Offringa via Std-Proposals <
>>> std-proposals_at_[hidden]> wrote:
>>>
>>>> Hi all,
>>>>
>>>> I was wondering what people think of the following idea. The problem
>>>> I'm
>>>> trying to address is that if we want to introduce a helper method for a
>>>> class, we have to declare this helper function in the class, e.g.
>>>> assume
>>>> this situation:
>>>>
>>>> == Header file: ==
>>>>
>>>> class Foo {
>>>> public:
>>>> void A();
>>>>
>>>> private:
>>>> void Helper();
>>>>
>>>> int value_;
>>>> };
>>>>
>>>> == Unit file: ==
>>>>
>>>> void Foo::A() {
>>>> ...
>>>> Helper();
>>>> ...
>>>> }
>>>>
>>>> void Foo::Helper() {
>>>> ...
>>>> value_ = ...;
>>>> ...
>>>> }
>>>>
>>>> I think it would be useful if there would be a way to skip the
>>>> declaration of the Helper method inside the class (in the header file),
>>>> and make it translation local just like a static function or function
>>>> inside an anonymous namespace would be. From the compiler's point of
>>>> view, it could then act as a translation-unit-local function, except
>>>> with the possibility to access (private) class fields.
>>>>
>>>> The benefit is that the method is no longer part of the "interface" of
>>>> the class, and this is useful because it is, after all, an
>>>> implementation detail of the class. This makes it also no longer
>>>> necessary to have the parameter types and return value type declared in
>>>> the header file, which decreases dependencies between files.
>>>>
>>>> An example of how this could look like, could be to use the keyword
>>>> 'private' and let it act as an identifier for declaring such a
>>>> function,
>>>> e.g.:
>>>>
>>>> == Header file: ==
>>>>
>>>> class Foo {
>>>> public:
>>>> void A();
>>>>
>>>> private:
>>>> int value_;
>>>> }
>>>>
>>>> == Unit file: ==
>>>>
>>>> private void Foo::Helper() {
>>>> ...
>>>> value_ = ...;
>>>> ...
>>>> }
>>>>
>>>> void Foo::A() {
>>>> ...
>>>> Helper();
>>>> ...
>>>> }
>>>>
>>>> Of course the syntax is open for discussion. The idea is that Helper()
>>>> is now a private translation-unit-local function that receives the
>>>> 'this' pointer and access to private fields. The function itself acts
>>>> in
>>>> name lookup as a free function, to avoid participating in member
>>>> lookup,
>>>> but is only visible inside class member functions or other private
>>>> translation-unit-local functions, and is not accessible outside of
>>>> that.
>>>> This makes it somewhat between a member function and a free function.
>>>> With such an approach, it can not be used to access private fields from
>>>> a scope that does not allow access to those fields. Hence, the class
>>>> data remains encapsulated. It should not modify the layout of the class
>>>> and not change its ABI. There are more details to think through.
>>>>
>>>> Thinking of alternatives, another direction to solve this would be to
>>>> change the standard such that friend functions can be declared as
>>>> friend
>>>> outside of the class definition, instead of by introducing a function
>>>> with special visibility rules. They would then behave as normal
>>>> functions, which simplify some details. This makes private data too
>>>> widely usable, so I don't see a good solution in that direction.
>>>>
>>>> Syntax aside, the problem I'm trying to solve is to have a function
>>>> that:
>>>> - has access to private members
>>>> - is defined only in the unit file
>>>> - does not require any declaration in the header
>>>> - does not become part of the class interface
>>>>
>>>> I think the best existing alternative for this situation is to declare
>>>> a
>>>> static free function in the unit file that takes as parameter the class
>>>> members it needs. In complex situations, this is not as nice. In pimpl
>>>> implementations it is a reasonable solution, but a pimpl pattern is not
>>>> always desired.
>>>>
>>>> I'm curious to hear what people think about the idea of private
>>>> translation-unit-local functions.
>>>>
>>>> Kind regards,
>>>> André Offringa
>>>>
>>>> --
>>>> Std-Proposals mailing list
>>>> Std-Proposals_at_[hidden]
>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>>>
>>>
>>> --
>>> Std-Proposals mailing list
>>> Std-Proposals_at_[hidden]
>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>>
>>
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2026-04-27 09:28:10