how to modify clang to allow bolt-on member functions?

#include
struct Foo {
int x;
void bar();
};
void Foo::bar() {//<<<<<< not declared in the class
std::cout<<x;
}
int main(int argc,const char** argv){
Foo f;f.x=10;
f.bar();
}

Could anyone comment how difficult it would be to modify my own build of clang to allow this to compile. (and provide pointers on which areas of the source to look at)

the motivation is to ease refactoring, and reduce the inconsistency between free functions and member functions. I find myself constantly alternating between them, and this article explains why…
http://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/184401197

I realise many people familiar with OOP discipline would object to this in principle, but its interesting to see how ‘rust’ and ‘go’ work with their ‘open world’ philosophy eg traits and implementations.

i wondered if it would break the language design to allow this - I would suggest Foo::bar above hasa the same acess rights as free functions . it seems like a simple idea, and it cant be so obscure as a solution to my ‘itch’ has appeared in go/rust

Hi Walter,

#include <iostream>
struct Foo {
    int x;
    void bar();
};
void Foo::bar() {//<<<<<< not declared in the class
    std::cout<<x;
}
int main(int argc,const char** argv){
    Foo f;f.x=10;
    f.bar();
}

Could anyone comment how difficult it would be to modify my own build of
clang to allow this to compile. (and provide pointers on which areas of the
source to look at)

I don't understand why you want to modify your compiler. This code
compiles fine with both g++ 4.5.3 and clang++ 3.3 (trunk 178973)

$ g++ -Wall -pedantic -W bolt-on.cpp
bolt-on.cpp:9:5: warning: unused parameter ‘argc’
bolt-on.cpp:9:5: warning: unused parameter ‘argv’

$ clang++ -Wall -pedantic -W bolt-on.cpp
bolt-on.cpp:9:14: warning: unused parameter 'argc' [-Wunused-parameter]
int main(int argc,const char** argv){
             ^
bolt-on.cpp:9:32: warning: unused parameter 'argv' [-Wunused-parameter]
int main(int argc,const char** argv){
                               ^
2 warnings generated.

Note that Foo::bar _is_ declared in the class (the "void bar();" line
inside struct Foo declares a function Foo::bar).

Csaba

oops - seems I posted the wrong example carelessly..
THIS is what i meant:-

#include <iostream>
struct Foo {
   int x; <<<< no declaration of Foo::bar() in the class
};
void Foo::bar() {//<<<<<< not declared in the class
   std::cout<<x;
}
int main(int argc,const char** argv){
  Foo f;f.x=10;
  f.bar();
}

Its an "itch" I have from long running frustrations with C++, and seeing rust/go & reading that article makes me think i can't be alone in this.

It probably wouldn't be too difficult to support this syntax (although getting non-standard syntactic extensions accepted into mainline clang is another story), but it would make the language weirdly inconsistent (more than it is already). You would be able to write this function out of line without the declaration, but not virtual functions, because their location in the class declaration defines the order (and size) of the vtable. You can already implement a function bar(Foo &f), so this doesn't add much to the language (it just avoids the need for friend declarations if you are accessing private members).

Non-virtual member functions in C++ are just a short-hand way of declaring which functions are implicitly allowed to access a class's private fields. If you remove this declaration requirement, then you remove even the vague notion of encapsulation that C++ pretends to provide.

David

(although getting non-standard syntactic extensions accepted into mainline clang is another story)
-yes i dont hold much hope for that, although a compiler switch enabling it would make my day

but it would make the language weirdly inconsistent

the point would be to make sourcecode more consistent. The author of the article makes the same observation - there are plenty of times when non-member/non-friend functions improve encapsulation, but the whole language syntax & OOP culture herds you toward making class members. So many coders (eg trained in java) are trained to use classes members exclusively. As unscientific as it sounds, even to me - a fan of free functions - “it just feels weird” having them side by side.

There’s Rust out there which is designed to avoid this problem (with its traits & implementations) - but changing to a new language (when C++ is ubiquitous) is scary. and of course Rust itself relies on LLVM and hence C++.
its very tempting for me at the minute- do I get behind an alternative language that makes the way I want to work more natural…

but not virtual functions, because their location in the class declaration defines the order (and size) of the vtable.

For me that is no problem - when you’re declaring a vtable, the class becomes more of a virtue than a hinderance. you really do need to be able to see the whole interface in one place - and yes, you’re declaring data aswell (the vtable) - and vtables themselves enable decoupling.
In my situations however vtables are avoided for performance reasons.

so this doesn’t add much to the language (it just avoids the need for friend declarations if you are accessing private members).

To appease those who DO rely on public/private - I would suggest that these ‘undeclared member functions’ should have the same access rights as any other non-member function.
For me it would ease refactoring …it would be much easier to shuffle code around between modules, when the issue of modules/namespaces is nolonger conflated with calling-convention (merely putting a parameter in a different place)