Why does the member function name lookup stay in the parent class? - c++

Motivation, if it helps: : I have struct member functions that are radial-basis-function kernels. They are called 1e06 x 15 x 1e05 times in a numerical simulation. Counting on devirtualization to inline virtual functions is not something I want to do for that many function calls. Also, the structs (RBF kernels) are already used as template parameters of a larger interpolation class.
Minimal working example
I have a function g() that is always the same, and I want to reuse it, so I pack it in the base class.
The function g() calls a function f() that is different in derived classes.
I don't want to use virtual functions to resolve the function names at runtime, because this incurs additional costs (I measured it in my code, it has an effect).
Here is the example:
#include <iostream>
struct A
{
double f() const { return 0; };
void g() const
{
std::cout << f() << std::endl;
}
};
struct B : private A
{
using A::g;
double f() const { return 1; };
};
struct C : private A
{
using A::g;
double f() const { return 2; };
};
int main()
{
B b;
C c;
b.g(); // Outputs 0 instead of 1
c.g(); // Outputs 0 instead of 2
}
I expected the name resolution mechanism to figure out I want to use "A::g()", but then to return to "B" or "C" to resolve the "f()" function. Something along the lines: "when I know a type at compile time, I will try to resolve all names in this type first, and do a name lookup from objects/parents something is missing, then go back to the type I was called from". However, it seems to figure out "A::g()" is used, then it sits in "A" and just picks "A::f()", even though the actual call to "g()" came from "B" and "C".
This can be solved using virtual functions, but I don't understand and would like to know the reasoning behind the name lookup sticking to the parent class when types are known at compile time.
How can I get this to work without virtual functions?

This is a standard task for the CRTP. The base class needs to know what the static type of the object is, and then it just casts itself to that.
template<typename Derived>
struct A
{
void g() const
{
cout << static_cast<Derived const*>(this)->f() << endl;
}
};
struct B : A<B>
{
using A::g;
double f() const { return 1; };
};
Also, responding to a comment you wrote, (which is maybe your real question?),
can you tell me what is the reasoning for the name lookup to stick to the base class, instead of returning to the derived class once it looked up g()?
Because classes are intended to be used for object-oriented programming, not for code reuse. The programmer of A needs to be able to understand what their code is doing, which means subclasses shouldn't be able to arbitrarily override functionality from the base class. That's what virtual is, really: A giving its subclasses permission to override that specific member. Anything that A hasn't opted-in to that for, they should be able to rely on.
Consider in your example: What if the author of B later added an integer member which happened to be called endl? Should that break A? Should B have to care about all the private member names of A? And if the author of A wants to add a member variable, should they be able to do so in a way that doesn't potentially break some subclass? (The answers are "no", "no", and "yes".)

Related

How are virtual constexpr function possible?

As of C++2a, virtual functions can now be constexpr. But as far as I know, you still cannot call arbitrary function pointers in constexpr context.
Dynamic polymorphism is usually implemented using a vtable, which contains the function pointer to call.
Also, dynamic polymorphism with virtual is useful to call overriding functions of a type you don't know which one it is at compile time. For example:
struct A {
virtual void fn() const {
std::cout << 'A' << std::endl;
}
};
void a_or_b(A const& a) {
// The compiler has no idea `B` exists
// it must be deferred at runtime
a.fn();
}
struct B : A {
void fn() const override {
std::cout << 'A' << std::endl;
}
};
int main() {
// We choose which class is sent
a_or_b(rand() % 2 ? A{} : B{});
}
So considering those that function pointers cannot be called at compile time and virtual polymorphism is used when the compiler don't have enough information to statically infer what function to call, how are virtual constexpr functions possible?
Please keep in mind that constexpr virtual functions would be called at compile time only when the type is already known to the compiler and obviously they would not be called through virtual dispatch.
Corresponding proposal provides similar explanation:
Virtual function calls are currently prohibited in constant
expressions. Since in a constant expression the dynamic type of the
object is required to be known (in order to, for example, diagnose
undefined behavior in casts), the restriction is unnecessary and
artificial. We propose the restriction be removed.
It also has a very nice motivating example.

Are virtual functions the only way to achieve Runtime Polymorphism in C++?

One of my friends asked me "How Runtime Polymorphism is achieved in C++?" I answered "By Inheritance"
He said "No, it can be achieved only using virtual functions".
So I gave him an example of the following code :-
#include<iostream>
using namespace std;
class A
{
public:
int i;
A(){i=100;}
};
class B : public A
{
public:
int j;
B(){i = -1; j = 99;}
};
void func(A& myA)
{
cout<<myA.i << endl;
}
int main()
{
B b;
A* a = new B();
func(*a);
func(b);
delete a;
return 0;
}
Here, function func() takes reference of A but we pass object of B and we can print the value of public member "i". He said it is compile time polymorphism.
My questions are :-
1) Is Runtime polymorphism achieved only with virtual functions?
2) Is the example above has runtime polymorphism or compile time?
3) If I have the following code :-
void func2(A& myA)
{
cout << myA.i << endl;
// dynamic/static cast myA to myB
cout<<myB.j << endl;
}
what kind of polymorphism is it? Or is it even polymorphism?
The example does not show dynamic polymorphism. The method to be called is known at compile time. There is no runtime decision(based on actual object type) as to which method should be called. There is no different behavior for different types.
For the example to be example of dynamic polymorphism.
You need to provide a virtual member function in Base class and overide it in derived class. The actual method to be called is decided by the actual type of the object pointed by the Base class pointer.
Online sample:
#include<iostream>
using namespace std;
class A
{
public:
virtual void doSomething()
{
std::cout<<"\nIn A::doSomething()";
}
};
class B : public A
{
public:
virtual void doSomething()
{
std::cout<<"\nIn B::doSomething()";
}
};
int main()
{
B b;
A obj;
A* a = &b;
a->doSomething();
a = &obj;
a->doSomething();
return 0;
}
Output:
In B::doSomething()
In A::doSomething()
Is Runtime polymorphism acheived only with virutal functions?
No, but virtual functions is the most common and correct way to do so.
Polymorphism can be achieved through function pointers. Consider the following code example, the actual method to call is decided at run-time depending on user input. It is a form of polymorphism through not in strict sense C++ sense which mandates different behaviors for different types.
#include <iostream>
typedef void (*someFunction)(int, char*);
void FirstsomeFunction(int i, char *c)
{
std::cout<<"\n In FirstsomeFunction";
}
void SecondsomeFunction(int i, char *c)
{
std::cout<<"\n In SecondsomeFunction";
}
int main()
{
someFunction arr[1];
int x = 0;
std::cin >> x;
if(x ==0)
arr[0] = &FirstsomeFunction;
else
arr[0] = &SecondsomeFunction;
(arr[0])(10,"Hello");
return 0;
}
Is the example above has runtime polymorphism or compile time?
There is no polymorphism of any kind. The same method will be called in all cases. There is no different behavior for different types and hence it does not classify as polymorphism of any kind.
The C language's fprintf is a polymorphic function.
You can pass it various handles and it can print to a file, stdout, a printer, a socket, anything which the system can represent as a stream.
FILE* file = fopen("output.txt", "w"); // a file
FILE* file = stdout; // standard output
FILE* file = fopen("/dev/usb/lp0", "w"); // a usb printer
FILE* file = popen("/usr/bin/lpr -P PDF", "w"); // a PDF file
FILE* file = fdopen(socket(AF_INET,SOCK_STREAM,0), "r+"); // network socket
fprintf(file, "Hello World.\n");
what you wrote is not polymorphism.
This is how you do polymorphism in C++ :
#include<iostream>
using namespace std;
class A
{
public:
virtual void func(){
cout << "printing A" << endl;
}
virtual ~A(){}
};
class B : public A
{
public:
void func(){
cout << "printing B" << endl;
}
};
int main()
{
A* a = new A();
A* b = new B();
a->func(); // "printing A"
b->func(); // "printing B"
delete a;
delete b;
return 0;
}
If you were to remove the virtual keyword, the method func of A would be called twice.
One of my friends asked me "How Runtime Polymorphism is achieved in C++?" I answered "By Inheritance"
He said "No, it can be achieved only using virtual functions".
First, the term polymorphism is ambiguous: in the general computing science sense it refers to an ability to implicitly invoke type-specific code, whether at compile time or run-time. In the C++ Standard it is defined very narrowly are being virtual dispatch (that's the perogative of standards). Obviously for your friend's question to be meaningful, as he's asking how it's achieved in C++ his perspective must be from outside C++ - in the larger context of Computing Science terminology.
Certainly, virtual functions/dispatch are an answer, but are they the only answer...?
To attempt to answer that, it helps to have a clear conception of what behaviour qualifies as run-time polymorphic. Consider:
void f(X& x)
{
// the only situation where C++ doesn't know the run-time type of a variable is
// where it's an instance of a class/struct accepted by reference or pointer
...some operation involving "x"...
}
Any mechanism that could result in different machine code for the operation being invoked involving "x", where the reason relates specifically to the run-time type of "x", is getting pretty close to run-time polymorphic, but there's one final issue: was that branching decided implicitly by the language, or arranged explicitly by the programmer?
In the case of virtual dispatch, the compiler implicitly knows to create the virtual dispatch tables and lookups that branch to the type-appropriate code.
But, say we have a function pointer that was previously set to address type-appropriate code, or a type-specific number or enum that is used to control a switch to a type-specific case. These functionally achieve the same behaviour as run-time virtual dispatch, but the set up had to be done explicitly by the developer, and there's no compiler enforcement to make sure that the determination is done purely on run-time type. Whether they qualify or not is arguable. Because C++ has a fully implicit mechanism in virtual dispatch, and because in the C++ Standard polymorphism has a narrowed definition related specifically to virtual dispatch, I'd guess that most C++ programmers would say "no".
But in the world of C, describing say qsort or bsearch (two Standard libC functions that handle arbitrary types using run-time dispatch via function pointer arguments) as run-time polymorphic might aid quick understanding... it's more normal to say that they're generic implementations though.
Still, there's doubtless hundreds of Computing Science textbooks out there with functional definitions of run-time polymorphism, and I'd bet dispatch using function pointers or other programmer-initialised metadata satisfied a good percentage of them. So, it's pointless to be too insistent that there's a single unambiguous answer.
My questions are :-
1) Is Runtime polymorphism achieved only with virtual functions?
As above, I'd lean towards "yes" in the context of C++, but it's (endlessly) arguable.
2) Is the example above has runtime polymorphism or compile time?
Neither... there's not even two functions to choose between on the basis of type - you're always running the same machine code for func(): that picked by the compiler given an expectation that the type is A.
3) If I have the following code :-
void func2(A& myA)
{
cout << myA.i << endl;
// dynamic/static cast myA to myB
cout<<myB.j << endl;
}
what kind of polymorphism is it? Or is it even polymorphism?
Not polymorphic at all, as you have no branching based on type. A dynamic cast could consult the compiler-populated type meta-data in the run-time type of myA, and if you used that to only conditionally invoke the access to myB.j - which would be undefined behaviour unless myA was a B - then you're back at manually, explicitly developer coordinated type-specific behaviour, and whether that qualifies as "polymorphism" for you is discussed above.
Polymorphism is achieved with virtual functions. But to have any effect, i.e. different behaviour depending on type, you need inheritance too
struct A {
virtual void f() = 0;
};
struct B : public A {
void f() {
// do B things
std::cout << "B::f() called\n";
}
};
struct C : public A {
void f() {
// do C things
std::cout << "C::f() called\n";
}
};
Now you can have pointers or references to A with different behaviour, depending on whether it's a B or C.
[C++]
Polymorphism is defined as one interface to control access to a general class of actions. There are two types of polymorphism one is compile time polymorphism and the other is run time polymorphism. Compile time polymorphism is functions and operators overloading. Runtime time polymorphism is done using inheritance and virtual functions.
Polymorphism means that functions assume different forms at different times. In case of compile time it is called function overloading. For example, a program can consist of two functions where one can perform integer addition and other can perform addition of floating point numbers but the name of the functions can be same such as add. The function add() is said to be overloaded. Two or more functions can have same name but their parameter list should be different either in terms of parameters or their data types. The functions which differ only in their return types cannot be overloaded. The compiler will select the right function depending on the type of parameters passed. In cases of classes constructors could be overloaded as there can be both initialized and uninitialized objects.

Accessing members from an object itself with either THIS or member scope

What is the proper way of accessing a member data/function that is part of the method's class? There appears to be 3 means:
class test{
private:
int variable;
public:
void setVariable(int value) {
variable = value; // method 1, using the variable name directly
this->variable = value; // method 2, via pointer dereference of 'this'
test::variable = value; // method 3, via scope operator
}
};
They all seems to work as far as I can tell. Are they equivalent? Is there a reason to use one over the other beside style/consistency?
In addition to style and consistency, as you mention, sometimes you have to use a specific syntax to disambiguate.
"method 2" can be used to disambiguate between local variables and class members.
"method 3" can be used to disambiguate between fields with the same name in different places of your class hierarchy.
In general it does not matter so the simpler options member = value; is preferred. In some cases there might be ambiguity with a local variable and there you can qualify with the this-> prefix, but a better approach would be avoid the ambiguity altogether.
There are however some corner cases where it does matter. When dealing with virtual functions, using a qualified name (type::member) disables runtime dispatch and ensures that the final overrider at the type level is called:
struct base {
virtual int f() { return 1; }
};
struct derived : base {
virtual int f() { return 2; }
void g() {
std::cout << f() << "\n";
std::cout << derived::f() << "\n";
}
};
struct mostderived : derived {
virtual int f() { return 3; }
};
int main() {
mostderived d;
d.g(); // 3 2
}
When dealing with template classes and inheritance, lookup is performed in two phases. During the first phase, non-dependent names have to be resolved. An unqualified name is a non-dependent name, so in some cases you need to qualify with either this-> or type::, and the distinction above still applies. The extra qualification serves to make the name dependent:
template <typename T>
struct derived : T {
void g() {
// std::cout << f() << "\n"; // Error, cannot resolve f() [*]
this->f(); // Ok, pick final overrider at runtime
derived::f(); // Ok, pick overrider here: base::f()
}
};
struct base {
virtual int f() { return 1; }
};
struct mostderived : derived<base> {
virtual int f() { return 3; }
};
int main() {
mostderived d;
d.g(); // 3, 1
}
For code inside the object, it generally makes no difference, so it's usually cleanest to just use variable = value; and be done with it.
Sometimes in a template, you can run into a situation where just using the variable name by itself is ambiguous, and this->variable removes that ambiguity -- but this is rare enough that I definitely would not use this->everything on a regular basis just because it might be useful once in a great while.
Method 1: This is the common way it is done.
Method 2: This is the best and most consistence way to do it. It makes it very clear to read and understand what's happening.
Method 3: I've never seen done in real world code.
As a side note: When using method 1 if there is a naming conflict with the function parameter and member variable the function parameter will be used over the member variable.
if we have:
void setVariable(int variable) {
variable = variable; // method 1, this does not change the member variable.
this->variable = variable; // method 2, via pointer dereference of 'this'
test::variable = variable; // method 3, via scope operator
}
The pointer this is often used for comparison in an overloaded operator of a class. One of its uses can be if the parameter passed in the function is the same as the object itself, for example:
class CDummy {
public:
int isitme (CDummy& param);
};
int CDummy::isitme (CDummy& param)
{
if (&param == this) return true;
else return false;
}
This is also used to return a pointer to the object itself
ClassEx ClassEx::Func(//params)
{
//code
return *this;
}
As for normal comparison, value instead of this->value will be more efficient to use, the use of this-> is ambiguous unless you're checking values.
There is no difference in performance. The :: is used to avoid ambiguities, such as when you have a local variable with same name of a field, or a base class that declares a field with same name of a field in a derived class. The -> is supported because the type of this is a pointer to object, so the compiler must accept this->something, and that can also be used to avoid ambiguities or just to let code more clear.
And to add to the above answers:
Some code styles like to identify member variables using a fixed prefix like _ or m. Using "method 2" is another (and imho much nicer way) of achieving this clarity in the code.
Prefering this->value over value is also a little like using std::cin instead cin with a using namespace std.
Use method 1
variable = value;
Saves you buying a new keyboard so frequently!
(Having said that I should stop stilling coffee over mine!)

Inheritance, pseudo polymorphism

Whilst digging through the STL sources (DinkumWare, SGI, STLport, etc..) and trying to make sense of their implementation choices (it's going well), I came across something I feel is a bit odd or rather ive never run into before.
Generally when one wishes to overload a member function in a derived class, you would prepend the base class member function signature with the virtual keyword, however at various points in the STL source this is not the case.
Here is a cut-down version of what I'm seeing in the STL implementations:
template <typename T> class A {
public:
void func( ) { std::cout << "inside A func( )" << std::endl; }
};
template <typename T> class B : public A<T> {
public:
void func( ) { std::cout << "inside B func( )" << std::endl; }
};
The compiler seems fine with this pseudo-polymorphism, where as I was expecting an error something along the lines of:
error C2535: 'void B<T>::func(void)': member function already defined or declared
Would someone be kind enough to explain what is going on here?
PS: This also seems to work without the classes being templates too.
'Regards
Without the virtual keyword - when redefining a function, you are hiding the super's function.
In your case, by redifining func(), you tell the compiler there is a new function for B, which is different from A's.
Though, because it is not declared virtual, you will see this affect only if you invoke func() from a variable of type B. A variable of type A which holds a B, will invoke A's func().
A *a = new B;
a->func()
will invoke the first [A's] method.
To invoke B's method, you need the type to be B:
B *b = new B;
b->func()
The B<T>::func member simply shadows A<T>::func. When you call p->func() where A<T> *p points to a B<T>, A<T>::func is called, so there's no polymorphism.
#include <iostream>
struct A
{
void func() { std::cout << "Hello!\n"; }
};
struct B : public A
{
void func() { std::cout << "Goodbye!\n"; }
};
int main()
{
B b;
A *p = &b;
p->func();
b.func();
}
(Demo)
In the C++ standard, there's at least one place where this shadowing/name hiding is exploited: std::ifstream::rdbuf hides its ancestor's method by that name and actually changes its return type.
There clearly is no error because these functions are just overloads: A::func() has a signature taking an A object (a reference or a pointer) as first argument while B::func() has a signature taking a B object as first argument. That is, this is just overloading of two functions with different argument but the function name.
This is done in a few places to produce a different return type from a function which is essentially trivially forwarding to another function (at least, these are the places I can think of). This is just to make life a bit easier for users although it is actually more confusing than anything else. The examples I can think of (e.g. the rdbuf() function in streams) should have created a different name instead.
This is acceptable code, B<T>::func is just hiding A<T>::func.
A<int> a;
B<int> b;
a.func(); // inside A
b.func(); // inside B
A<int> *const pA = new B<int>();
pA->func(); // inside A
When calling func through a polymorphic type, it will call the function on the type of the pointer.

The mechanics of extension via free functions or member functions

Loads of C++ libraries, the standard included, allow you to adapt your objects for use in the libraries. The choice is often between a member function or a free function in the same namespace.
I'd like to know mechanics and constructs the library code uses to dispatch a call which will call one of these "extension" functions, I know this decision has to take place during compile time and involves templates. The following runtime psuedocode is not possible/non-sense, the reasons are out of the scope of this question.
if Class A has member function with signature FunctionSignature
choose &A.functionSignature(...)
else if NamespaceOfClassA has free function freeFunctionSignature
choose freeFunctionSignature(...)
else
throw "no valid extension function was provided"
The code above looks like runtime code :/. So, how does the library figure out the namespace a class is in, how does it detect the three conditions, what other pitfalls are there that need to be avoided.
The motivation for my question is for me to be able to find the dispatch blocks in libraries, and to be able to use the constructs in my own code. So, detailed answers will help.
!!TO WIN BOUNTY!!
Ok so according to the answer from Steve (and the comments) ADL and SFINAE are the key constructs for wiring up the dispatch at compile time. I've got my head arround ADL (primitively) and SFINAE (again rudementary). But I don't know how they orchistrate together in the way I think they should.
I want to see a illustrative example of how these two constructs can be put together so that a library can choose at compile time whether to call a user supplied member function in an object, or a user supplied free function supplied in the same object's namespace. This should only be done using the two constructs above, no runtime dispatch of any sort.
Lets say the object in question is called NS::Car, and this object needs to provide the behaviour of MoveForward(int units), as a member function ofc. If the behaviour is to be picked up from the object's namespace it will probably look like MoveForward(const Car & car_, int units). Lets define the function that wants to dispatch mover(NS::direction d, const NS::vehicle & v_) , where direction is an enum, and v_ is a base class of NS::car.
The library doesn't do any of this at runtime, dispatch is done by the compiler when the calling code is compiled. Free functions in the same namespace as one of the arguments are found according to the rules of a mechanism called "Argument-Dependent Lookup" (ADL), sometimes called "Koenig lookup".
In cases where you have the option either to implement a free function or a member function, it may be because the library provides a template for a free function that calls the member function. Then if your object provides a function of the same name by ADL, it will be a better match than instantiating the template, and hence will be chosen first. As Space_C0wb0y says, they might use SFINAE to detect the member function in the template, and do something different according to whether it exists or not.
You can't change the behaviour of std::cout << x; by adding a member function to x, so I'm not quite sure what you mean there.
Well, I can tell you how to detect the presence of member functions of a certain name (and signature) at compile time. A friend of mine describes it here:
Detecting the Existence of Member Functions at Compile-Time
However that won't get you where you want to go, because it only works for the static type. Since you want to pass a "reference-to-vehicle", there is no way to test if the the dynamic type (the type of the concrete object behind the reference) has such a member function.
If you settle for the static type though, there is another way to do a very similar thing.
It implements "if the user provides an overloaded free function, call it, otherwise try to call the member function". And it goes like this:
namespace your_ns {
template <class T>
void your_function(T const& t)
{
the_operation(t); // unqualified call to free function
}
// in the same namespace, you provide the "default"
// for the_operation as a template, and have it call the member function:
template <class T>
void the_operation(T const& t)
{
t.the_operation();
}
} // namespace your_ns
That way the user can provide it's own overload of "the_operation",
in the same namespace as his class, so it's found by ADL. Of course
the user's "the_operation" must be "more specialized" than your default
implementation - otherwise the call would be ambiguous.
In practice that's not a problem though, since everything that restricts
the type of the parameter more than it being a reference-to-const to anything will be
"more specialized".
Example:
namespace users_ns {
class foo {};
void the_operation(foo const& f)
{
std::cout << "foo\n";
}
template <class T>
class bar {};
template <class T>
void the_operation(bar<T> const& b)
{
std::cout << "bar\n";
}
} // namespace users_ns
EDIT: after reading Steve Jessop's answer again, I realize that's basically what he wrote, only with more words :)
If you're just looking for a concrete example, consider the following:
#include <cassert>
#include <type_traits>
#include <iostream>
namespace NS
{
enum direction { forward, backward, left, right };
struct vehicle { virtual ~vehicle() { } };
struct Car : vehicle
{
void MoveForward(int units) // (1)
{
std::cout << "in NS::Car::MoveForward(int)\n";
}
};
void MoveForward(Car& car_, int units)
{
std::cout << "in NS::MoveForward(Car&, int)\n";
}
}
template<typename V>
class HasMoveForwardMember // (2)
{
template<typename U, void(U::*)(int) = &U::MoveForward>
struct sfinae_impl { };
typedef char true_t;
struct false_t { true_t f[2]; };
static V* make();
template<typename U>
static true_t check(U*, sfinae_impl<U>* = 0);
static false_t check(...);
public:
static bool const value = sizeof(check(make())) == sizeof(true_t);
};
template<typename V, bool HasMember = HasMoveForwardMember<V>::value>
struct MoveForwardDispatcher // (3)
{
static void MoveForward(V& v_, int units) { v_.MoveForward(units); }
};
template<typename V>
struct MoveForwardDispatcher<V, false> // (3)
{
static void MoveForward(V& v_, int units) { NS::MoveForward(v_, units); }
};
template<typename V>
typename std::enable_if<std::is_base_of<NS::vehicle, V>::value>::type // (4)
mover(NS::direction d, V& v_)
{
switch (d)
{
case NS::forward:
MoveForwardDispatcher<V>::MoveForward(v_, 1); // (5)
break;
case NS::backward:
// ...
break;
case NS::left:
// ...
break;
case NS::right:
// ...
break;
default:
assert(false);
}
}
struct NonVehicleWithMoveForward { void MoveForward(int) { } }; // (6)
int main()
{
NS::Car v; // (7)
//NonVehicleWithMoveForward v; // (8)
mover(NS::forward, v);
}
HasMoveForwardMember (2) is a metafunction that checks for the existence of a member function of that name with the signature void(V::*)(int) in a given class V. MoveForwardDispatcher (3) uses this information to call the member function if it exists or falls back to calling a free function if it doesn't. mover simply delegates the invocation of MoveForward to MoveForwardDispatcher (5).
The code as-posted will invoke Car::MoveForward (1), but if this member function is removed, renamed, or has its signature changed, NS::MoveForward will be called instead.
Also note that because mover is a template, a SFINAE check must be put in place to retain the semantics of only allowing objects derived from NS::vehicle to be passed in for v_ (4). To demonstrate, if one comments out (7) and uncomments (8), mover will be called with an object of type NonVehicleWithMoveForward (6), which we want to disallow despite the fact that HasMoveForwardMember<NonVehicleWithMoveForward>::value == true.
(Note: If your standard library does not come with std::enable_if and std::is_base_of, use the std::tr1:: or boost:: variants instead as available.)
The way this sort of code is usually used is to always call the free function, and implement the free function in terms of something like MoveForwardDispatcher such that the free function simply calls the passed in object's member function if it exists, without having to write overloads of that free function for every possible type that may have an appropriate member function.
Altought, sometimes, developers can used free functions or class functions, interchangeably, there are some situations, to use one another.
(1) Object / Class functions ("methods), are prefered when most of its purpouse affect only the object, or objects are inteded to compose other objects.
// object method
MyListObject.add(MyItemObject);
MyListObject.add(MyItemObject);
MyListObject.add(MyItemObject);
(2) Free ("global" or "module") functions are prefered, when involves several objects, and the objects are not part / composed of each other. Or, when the function uses plain data (structs without methods, primitive types).
MyStringNamespace.MyStringClass A = new MyStringNamespace.MyStringClass("Mercury");
MyStringNamespace.MyStringClass B = new MyStringNamespace.MyStringClass("Jupiter");
// free function
bool X = MyStringNamespace.AreEqual(A, B);
When some common module function access objects, in C++, you have the "friend keyword" that allow them to access the objects methods, without regarding scope.
class MyStringClass {
private:
// ...
protected:
// ...
// not a method, but declared, to allow access
friend:
bool AreEqual(MyStringClass A, MyStringClass B);
}
bool AreEqual(MyStringClass A, MyStringClass B) { ... }
In "almost pure object oriented" programming languages like Java or C#, where you can't have free functions, free functions are replaced with static methods, which makes stuff more complicated.
If I understood correctly your problem is simply solved using (maybe multiple) inheritance. You have somewhere a namespace free function:
namespace NS {
void DoSomething()
{
std::cout << "NS::DoSomething()" << std::endl;
}
} // namespace NS
Use a base class which forwards the same function:
struct SomethingBase
{
void DoSomething()
{
return NS::DoSomething();
}
};
If some class A deriving from SomethingBase does not implement DoSomething() calling it will call SomethingBase::DoSomething() -> NS::DoSomething():
struct A : public SomethingBase // probably other bases
{
void DoSomethingElse()
{
std::cout << "A::DoSomethingElse()" << std::endl;
}
};
If another class B deriving from SomethingBase implement DoSomething() calling it will call B::DoSomething():
struct B : public SomethingBase // probably other bases
{
void DoSomething()
{
std::cout << "B::DoSomething()" << std::endl;
}
};
So calling DoSomething() on an object deriving from SomethingBase will execute the member if existing, or the free function otherwise. Note that there is nothing to throw, you get a compile error if there is no match to your call.
int main()
{
A a;
B b;
a.DoSomething(); // "NS::DoSomething()"
b.DoSomething(); // "B::DoSomething()"
a.DoSomethingElse(); // "A::DoSomethingElse()"
b.DoSomethingElse(); // error 'DoSomethingElse' : is not a member of 'B'
}