Hi Matthew,I did briefly read your proposal.You touch on this a little in your proposal, but just to be clear 9.4p5 [class.static]:> When used in the declaration of a class member, the static specifier shall only be used in the member declarations that appear within the member-specification of the class definition.So this is currently ill-formed:struct X{void f();};static void X::f() {} // ERRORThis frees the static specifier up to be used to specify a static member function if that is what you want. There is no ambiguity with the internal linkage meaning on a free function. In the event someone accidentally places static in front of a private extension method, intending internal linkage but getting a static member function, then the only effect is a compile-time error when they try to access the implicit object parameter that doesn't exist. It isn't dangerous.
You might also want to consider giving private extension methods implicit internal linkage (both static and non-static member functions), the only use case I can imagine is placing them in the .cpp so the linker doesn't even need to see the symbol, and if you really do want them to have external linkage you can always declare them in the class specifier as normal.
Your proposal breaks a current rule that a qualified declarator id has to be declared unqualified previously in the TU. This might cause a minor hassle to implementors with name lookup on declarator ids during parsing.
I think the main resistance you will receive is from people that claim that this would break encapsulation.
Currently the only entities that can access private members are all declared in the class specifier (either as members or friends). Some will claim that this is a nice property for programming in the large, as you can isolate what can be messing with private data to a list of possible culprits all in one place.
A private extension method, on the other hand, can be declared anywhere in the codebase. I'm however on your side fwiw, and think that having private member functions not cluttering the class specifier outweighs the loss.
Also you might want to spend some time studying the interaction with template classes. I assume you can also define private extension methods of template classes too? How will they interact with specialization/instantiation?
Good luck,Andrew.
I would also like to ask if I understand you correctly in that you are
suggesting to allow
#include "foo.hh"
namespace {
void foo::gazonk() { /* something */ }
}
and here foo::gazonk is a private member of foo?
/MF
Hello everyone, I am going to submit a proposal for relaxing the restriction on requiring private non-virtual class methods and static private class methods to be declared in the class definition.The github repository with the current draft of the proposal is here:
I would like to see a paragraph exploring if it feature could or not allow of the interface "leak", potentially breaking the encapsulation, maybe not in a harmful way, I'm not sure.
I think the main resistance you will receive is from people that claim that this would break encapsulation.
//foo.cc//foo.hh class Foo {
struct detail;
friend
detail
;public: Foo(); void pub1(); void pub2(); private: int _i; int _j; };
This idiom solves most of the problem the proposal address and doesn't have the drawback pointed by Jöel, as the detail class is private and no other can add private functions.
struct Foo::
detail
{ Foo& that;
detail
(Foo* f) : that(*f) {}
//Definition of _priv1() void _priv1() { /* function body */ }
//A new scoped private extension method. static void _priv3() { that._i = 3; }
}; //Definition of Foo::pub1() void Foo::pub1() {
detail
(this)._priv1();detail
(this).
_priv3(); }
//Forward declaration of a private extension method
void Foo::_priv2();
//Inlined public method calls the private extension method
inline void Foo::pub2() { _priv2(); }
inlining the _priv2() call would result on the same code.
I don't see neither the needed to declare new private
functions on different files. Could you explain where this could
be useful.
//foo.hh class Foo { public: Foo(); void pub1(); void pub2(); private: int _i; int _j; };
//foo.cc
Foo
private
{
//Definition of _priv1() void _priv1() { /* function body */ }
//A new scoped private extension method. static void _priv3() { _i = 3; }
}; //Definition of Foo::pub1() void Foo::pub1() { _priv1();_priv3(); }
give the guns, if people point to their feet and pull the trigger, we can't be
blamed.
That can already be done if the interface designer left a loophole: a class
friend that isn't defined in this compilation unit.
class Bar;
class Foofriend Bar;
{
// ...
private:
int k;
};
// headerclass Foo{// ...
private:int k;class Bar; // inner class, private so even if you have Bar interface, you can't use it from outside Foo's implementation};// cppclass Foo::Bar{// takes a Foo instance and access it's private members.
};
// user cppclass Foo::Bar // ODR violation, maybe hidden in case of dynamic libraries?{// do whatever with Foo// can't use it's interface as Foo::Bar name is not accessible anyway, so only Foo members// can use this type// If it's a dynamic library, this implementation will never be used by non-inline Foo member functions.};
// header
class Foo
{
// ...
private:
int k;
extension Bar; // like an inner class, private so even if you have Bar interface, you can't use it from outside Foo's implementation
};
// cpp
extension Foo::Bar
{
// Foo& m_foo;
// Bar( Foo& foo ) : m_foo( foo ) {}
Bar& inc_counter() { ++m_foo.k; return this; }
};
void Foo::action() { inc_counter(); } // here we use Foo::Bar, but in an implicit way
// user cpp
extension Foo::Bar // ODR violation, maybe hidden in case of dynamic libraries?
{
// do whatever with Foo
// can't use it's interface as Foo::Bar name is not accessible anyway, so only Foo members
// can use this type
// If it's a dynamic library, this implementation will never be used by non-inline Foo member functions.
isnt private extension still private? I every one can create private function but only private function can call it you can only create dead code.
To even call any new private extension you need have at least one normal member function to call it.
isnt private extension still private? I every one can create private function but only private function can call it you can only create dead code.
To even call any new private extension you need have at least one normal member function to call it.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
Hi,I love this proposal and wanted to do pretty much the same thing for some time.
In "Alternate Syntax", you say: "One downside of the current approach is that previously if the user wrote a typo when writing a member function name in the definition they would get a helpful compilation error."In my opinion, this is a deal breaker.
I think it's absolutely necessary to use a keyword for this, and I strongly recommend using 'private'.
On a side note, if you want some evidence for the value of this proposal, you should check out the Sema implementation of Clang. There's lots of static helper functions in the implementation files, they all get passed the Sema object, and quite a few of them should have been private members, because they force Sema members to be public that shouldn't have been.
This proposal is interesting.Minor side comment: I'm not sure if the word "method" is used correctly here. I see what you mean but my understanding is that depending on the language, method can mean virtual member function.
I remember C++ people saying that in C++ we should use member function to clarify that it have nothing to do with dynamic dispatch.
More importantly:I would like to see a paragraph exploring if it feature could or not allow of the interface "leak", potentially breaking the encapsulation, maybe not in a harmful way, I'm not sure.I mean: at first read of this proposal, it looks like it's not possible to call an extended private member function without it being called by another member function that ultimately
would be in the class interface.
However, it seems possible to break the encapsulation this way:///////////////////////////////////////////////////////////////////// Header "mylib.hpp" from an library "MyLib"namespace mylib{
class Foo{// ...private:
int k; // never exposed in the public interface};}///////////////////////////////////////////////////////////////////////// header "mycode.hpp" in the user code#include <mylib.hpp>namespace mylib{int* Foo::get_k() { return &this->k; } // private extension}///////////////////////////////////////////////////////////////////// cpp in the user code#include <mycode.hpp>void break_in( mylib::Foo& foo ){auto private_k_ptr = foo.get_k(); // accessing private members "legally"}////////////////////////////////////////////////////////////////////////
Could you clarify what would prevent this to be allowed? If it is allowed, then maybe clarifying if it's not a problem?
And if it is a problem, then I think the proposal is problematic.
However I'm not expert so I certainly missed something?
To add to my previous comment:Basically it looks to me that until we have a way to hide the types of the private member data, I can't see how it would be possible to avoid this kind of encapsulation breakage.
On 9 December 2013 21:26, Andrew Tomazos <andrew...@gmail.com> wrote:I think the main resistance you will receive is from people that claim that this would break encapsulation.Claim? Are you claiming this doesn't break encapsulation?
I don't see any benefit to inline calls to private functions that would be defined in a .cc file as your//Forward declaration of a private extension method void Foo::_priv2(); //Inlined public method calls the private extension method inline void Foo::pub2() { _priv2(); }
inlining the _priv2() call would result on the same code.
I don't see neither the needed to declare new private functions on different files. Could you explain where this could be useful.
Maybe the idiom could be adapted to a language proposal that could avoid the cumbersome use of the that variable. It could consists in declaring a pseudo-struct declaration e.g. private Foo, that could contain only functions. These functions would be accessible only by the class Foo and any friend of Foo. Of course, in order to other classes to be able to use these private functions, the private pseudo-struct should be declared in another file.
//foo.hh class Foo { public: Foo(); void pub1(); void pub2(); private: int _i; int _j; };
//foo.cc
Foo
private
{
//Definition of _priv1() void _priv1() { /* function body */ }
//A new scoped private extension method. static void _priv3() { _i = 3; }
};
//Definition of Foo::pub1() void Foo::pub1() { _priv1();
_priv3(); }
It is clear that all this would have less sense with modules.
I am strongly against making it this trivial to ignore encapsulation.
However, it is really easy to get any private data exposed in the class definition using extends methods,without having to change the class definition at all (which is worse than friend which at least force the userto change the library code, which have huge impact on maintenance, which is a big pressure not to do soif it's not for a bugfix but for abuse).
I'm not sure if it would be possible to modify your proposal so that it gives similar garantees to inner classes,but with easier syntax? At the moment I can't think of a good way.
Side comment: It looks like the issue the proposal is trying to partially fix is really hard to improve without changing at least a bit
the compilation model itself.
On 11 December 2013 00:59, Vicente J. Botet Escriba
<vicent...@wanadoo.fr> wrote:
> Le 10/12/13 23:46, Thiago Macieira a écrit :
>> class Bar;
>> class Foo
>> {
>> // ...
>> private:
>> int k;
>> friend Bar;
>> };
>>
>>
>> /// hack.cpp
>> class Bar
>> {
>> static int &get_k(Foo *d) { return d->k; }
>> };
>>
>>
>> To be honest, I don't know what the standard says about two different
>> declarations of the same class in the same application but not the same
>> translation unit. But the above will compile in most ABIs.
>
> This violated the ODR.
Which bit of it does that, exactly?
Here's one way to violate encapsulation with this extension:class A {int n;public:A() : n(42) {}};template<typename T> struct X {static decltype(T()()) t;};template<typename T> decltype(T()()) X<T>::t = T()();
int A::*p;private int A::expose_private_member() { // note, not called anywherestruct DoIt {int operator()() {p = &A::n;return 0;}};return X<DoIt>::t; // odr-use of X<DoIt>::t triggers instantiation}int main() {A a;return a.*p; // read private member}
A better way to violate privileges without violating the ODR would be to
explicitly specialize a member of Bar which cannot be named by another
TU. There are other tricks based on specialization.
What if a derived class meeting some strict requirements could be
defined as alias-compatible with the base, such that an object of a base
class could be used as the interface, and suitably casted used as the
implementation?
Extension methods are nice to have and closely related to modules.
Perhaps someone can draft a modules-compatible, self-contained extension
providing private implementation semantics, and get a head start on ABI
work related to consequences in the type system.
Wow lots of comments.
I don't see any benefit to inline calls to private functions that would be defined in a .cc file as your
//Forward declaration of a private extension method void Foo::_priv2(); //Inlined public method calls the private extension method inline void Foo::pub2() { _priv2(); }
inlining the _priv2() call would result on the same code.
I don't see neither the needed to declare new private functions on different files. Could you explain where this could be useful.
I've had plenty of situations where a class is implemented in multiple cc files in order to better separate concerns. I find myself doing this more for classes that implement "Application Logic." Usually singular concepts such as data structures are implemented in one cc file, if not entirely in the header due to templates.
In this situation, you would have your public header with the class definition, a private header with some extension method declarations, and finally multiple cc files with the definitions and possibly more file scoped extension methods as needed.
I understand your use case. Reducing compilation dependencies between implementation of different classes seems to me the problem to address. While taking care of the case where multiple files implements a specific class would be nice, it is for me a corner case.
Declaring an extension method in the same header as the class definition has little if no value. That's merely a stylistic choice. I included it just to show the possibilities.
Maybe the idiom could be adapted to a language proposal that could avoid the cumbersome use of the that variable. It could consists in declaring a pseudo-struct declaration e.g. private Foo, that could contain only functions. These functions would be accessible only by the class Foo and any friend of Foo. Of course, in order to other classes to be able to use these private functions, the private pseudo-struct should be declared in another file.
//foo.hh class Foo { public: Foo(); void pub1(); void pub2(); private: int _i; int _j; };
//foo.cc
Foo
private
{
//Definition of _priv1() void _priv1() { /* function body */ }
//A new scoped private extension method. static void _priv3() { _i = 3; }
};This is an interesting idea. Essentially reopening the scope to add more private stuff. Not only could you add new private methods but also private typedefs and nested classes as well. In the old thread (see github for the link), someone was essentially proposing this idea. He wanted to use a concept of class namespaces, but I like your syntax better.
//foo.hh
class Foo {
friend Foo;
};
//Definition of Foo::pub1() void Foo::pub1() { _priv1();
_priv3(); }
It is clear that all this would have less sense with modules.
Modules. Who knows what they are or when we will have them. I want something to solve my problems now. Also this can be a step towards modules.
Le 11/12/13 03:55, fmatth...@gmail.com a écrit :
I understand your use case. Reducing compilation dependencies between implementation of different classes seems to me the problem to address. While taking care of the case where multiple files implements a specific class would be nice, it is for me a corner case.Wow lots of comments.
I don't see any benefit to inline calls to private functions that would be defined in a .cc file as your
//Forward declaration of a private extension method void Foo::_priv2(); //Inlined public method calls the private extension method inline void Foo::pub2() { _priv2(); }
inlining the _priv2() call would result on the same code.
I don't see neither the needed to declare new private functions on different files. Could you explain where this could be useful.
I've had plenty of situations where a class is implemented in multiple cc files in order to better separate concerns. I find myself doing this more for classes that implement "Application Logic." Usually singular concepts such as data structures are implemented in one cc file, if not entirely in the header due to templates.
In this situation, you would have your public header with the class definition, a private header with some extension method declarations, and finally multiple cc files with the definitions and possibly more file scoped extension methods as needed.
So we agree this is not a must have.
Declaring an extension method in the same header as the class definition has little if no value. That's merely a stylistic choice. I included it just to show the possibilities.
Note that for me the scope could be reopened only once. In order to avoid that the user can do it on any class it would be better to restrict it to class that have declared it. E.g. we could declare the class friend of itself.
Maybe the idiom could be adapted to a language proposal that could avoid the cumbersome use of the that variable. It could consists in declaring a pseudo-struct declaration e.g. private Foo, that could contain only functions. These functions would be accessible only by the class Foo and any friend of Foo. Of course, in order to other classes to be able to use these private functions, the private pseudo-struct should be declared in another file.
//foo.hh class Foo { public: Foo(); void pub1(); void pub2(); private: int _i; int _j; };
//foo.cc
Foo
private
{
//Definition of _priv1() void _priv1() { /* function body */ }
//A new scoped private extension method. static void _priv3() { _i = 3; }
};This is an interesting idea. Essentially reopening the scope to add more private stuff. Not only could you add new private methods but also private typedefs and nested classes as well. In the old thread (see github for the link), someone was essentially proposing this idea. He wanted to use a concept of class namespaces, but I like your syntax better.
};
//foo.hh class Foo { friend Foo;
You are right, but you will not have a new feature before 2017 as minor as it can be.
//Definition of Foo::pub1() void Foo::pub1() { _priv1();
_priv3(); }
It is clear that all this would have less sense with modules.
Modules. Who knows what they are or when we will have them. I want something to solve my problems now. Also this can be a step towards modules.
Actually using a keyword nicely solves the static dilemna:private Foo::f1() //private extension methodprivate static Foo::f2() //static private methodstatic private Foo::f3() //private extension method with internal linkagestatic private static Foo::f4() //static private extension method with internal linkageGoing to think about it more, maybe using the private keyword makes sense.
Everyone, I have written a new draft after taking in all of the feedback. It is available on github.
With regards to method vs member function. It looks like some people use them interchangably while others prefer "method" for virtual functions. I am going to continue using the work method as its already in the name of the proposal.
Rather than have 'static private static' mean something different from 'static private', have you considered giving private extension methods interrnal linkage by default? (And require 'extern' in the presumably-rare case that they're actually meant to be declared and used in multiple translation units.)
Sorry this comment is too late for the mailing, but...
--
- I agree with the purpose of the proposal. I write APIs for a living. I'd prefer to keep out anything that doesn't need to be seen.- a bug in the paper (?)://Declare a PEM in the class header file.
//In this case, the effect is the same as declaring it within the class
//definition. Using an extension method here instead of declaring in the
//class definition is merely a stylistic choice.
Foo::_priv2();
//pub2() is inlined and calls _priv1() and _priv2(), so we need to see
//both of them at this point. This can be accomplished by including them
//within the class definition or declaring an extension method as shown
//by the examples of _priv1() and _priv2().
inline int pub2() { return _priv1() + _priv2(); }That _priv2 needs be to (I think/hope):private Foo::_priv2();
That _priv2 needs be to (I think/hope):private Foo::_priv2();
and the pub2() needs to be declared in the class, and qualified with Foo:: outside the class.
And/Or I don't understand what this part is trying to say.- In general, I prefer the "reopen Foo" syntax. I don't like private functions scattered around. You could still reopen Foo multiple times (and thus have it scattered around) but at least you could recommend against that in a style guideline. As an example:void Foo::function(){int x = bar();}is bar() a member function of Foo? We can no longer just look in the class definition to determine that. Now bar() could be declared "anywhere" (actually anywhere above the current code, including #includes, but practically anywhere). With reopening Foo, there will at least be a _tendency_ for it to only be reopened at the top of the file and/or a foo_impl.hh file.
Also reopening appears to allow private typedefs, nested classes, static variables, etc. Which all looks good to me.
Also, a normal function can be declared within any scope. Can a PEM:void func(){extern int f();int x = f();private int Foo::blah();int y = someFoo.blah(); // of course func() would need to be a friend here}
orvoid Foo::function(){private int blah(); // Foo:: not needed???int x = blah();}
- you might entertain using the 'continue' keyword to continue Foo:class continue Foo{int asdf(); // PEM};although using 'private' does help remind us that only private stuff is allowed.
- Internal Linkage by default: Definitely.
I would favor internal linkage by default.
The cases when you split one class into multiple TUs is very low. How about using the now abandoned export keyword instead of extern for the case that you really want to work with multiple TUs for one class. Or I would favor to make it impossible to use private extension methods over TU borders.
The paper seems to have a bug in the nested class workaround example:X:doWork must send *this rather than x to worker methods!
The table at the top of the paper does not list static data members. It would be possible to add private static data PEM-style. However the value is very limited as it is only a naming difference. However I think it should be in the table and be explained why it is not needed.
On Tuesday, January 28, 2014 11:41:58 PM UTC-5, Tony V E wrote:Also reopening appears to allow private typedefs, nested classes, static variables, etc. Which all looks good to me.I'm not sure how useful these things would be in practice when you can just create these objects with internal linkage. I'm not against it though, especially if someone can come up with a compelling use case.