Date: Mon, 27 Apr 2026 09:21:06 +0200
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.
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
>
>
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.
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
>
>
Received on 2026-04-27 07:21:12
