Embedded structs and correct function calls - c++

You're given two structs. One of type 'A', another of type 'B'.
The one of type 'B' has a struct of type 'A' in it. So something like this:
struct A {
void print_stuff(A * a){ puts("From A"); }
};
struct B {
A a_part;
char * s;
void print_stuff(B * b){
printf("From B\n\t%s\n", b->s);
}
};
B * B_new(char * str) {
B * b = (B*)malloc(sizeof(struct B));
b->s = strdup(str);
return b;
}
You want to be able to call struct B's 'print_stuff' function, even with code like this:
A * aptr = (A*) B_new("foo");
aptr->print_stuff(aptr);
You are NOT allowed to use inheritance, C++ containers or classes. Struct B MUST have a_part.
How would you write your code so that regardless of the type of the pointer, the correct print_stuff function is called (in this case, if a pointer to a struct of type B was casted to A*, how would you guarantee that the print_stuff function in B is called)?

You could make print_stuff a function pointer, but then you need to manually hook it up to the correct function. In this case though, you're just replicating C++ inheritance mechanisms so it's pointless.
The A object can't automatically know where it's contained, or if it's contained at all.
So the bottom line is, just use C++ inheritance.

This is really horrible. But yes, there is a way to do it. Put a bool field in A, and in the same place in B, to indicate the real type. The code below should give you an appreciation of C++ (and really shouldn't be used for any other purpose).
struct A {
bool isB;
A()
{
isB=false;
}
void print_stuff(A * a);
};
struct B {
bool trueB;
A a_part;
char * s;
B()
{
isB=true;
}
void print_stuff(B * b){
printf("From B\n\t%s\n", b->s);
}
};
void A::print_stuff(A * a)
{
if(isB)
{
B* b = (B*)(this);
b->print_stuff(b);
}
else
puts("From A");
}
B * B_new(char * str) {
B * b = (B*)malloc(sizeof(struct B));
b->s = strdup(str);
b->trueB=true;
return b;
}

Related

multi inheriting a struct from struct and template struct, ordering matters when accessing base non-template struct data

#include <stdlib.h>
#include <string>
#include <atomic>
struct base_C_event {
const char* ev;
const char* da;
};
template <class T>
struct ref_counter {
private:
std::atomic<std::ptrdiff_t> _counter;
};
struct derived_event : ref_counter<derived_event>, base_C_event {
derived_event() : event_type(), event_data() {
ev = event_type.c_str();
da = event_data.c_str();
}
std::string event_type;
std::string event_data;
};
struct derived_event2 : base_C_event, ref_counter<derived_event2> {
derived_event2() : event_type(), event_data() {
ev = event_type.c_str();
da = event_data.c_str();
}
std::string event_type;
std::string event_data;
};
struct some_cool_event {
int type;
void* payload;
};
void OnEvent(const some_cool_event* event) {
auto e = static_cast<base_C_event*>(event->payload); //...and then shows itself here
printf("%s - %s\n", e->ev, e->da);
}
int main() {
derived_event evt;
evt.event_type = "type";
evt.event_data = "Hello World";
derived_event2 evt2;
evt2.event_type = "hi";
evt2.event_data = "there";
some_cool_event my_event;
my_event.type = 1;
my_event.payload = &evt; //Problem starts here...
OnEvent(&my_event);
my_event.type = 2;
my_event.payload = &evt2;
OnEvent(&my_event);
return 0;
}
output: (compiled with g++)
(null) - type
type - Hello World
now, in my real environment (XCode) the ordering of inheritance for derived_event causes a BADACCESS exception; with g++ it just produces (null) as shown in the output.
however, the ordering for derived_event2 works just fine.
The way i understand the standard, the order of multiple inheritance effects the order of constructors and destructors, and also the layout of the memory. Can anyone explain what is happening here?
EDIT:
I have actually figured this out. The line that sets the event object to the void* payload, and then the ensuing static_cast<> back to the base type... seems to invalidate the first pointer (ev) because the struct becomes just a memory layout at that point, so the pointers are getting set to the first two pointer size chunks... in this case std::atomic<std::ptrdiff_t> and then the base_C_event. so the cast is grabbing the data for the std::atomic and using that as the pointer address for ev, and what was originally ev in the derived object is now what da points at.
I unfortunately in my real scenario can't use composition for the base_C_event in my derived_event and send that. that's why the refcounting is there, so i have to send the derived object so that later on in a callback i can decrement the refcount.
Is there a way to prevent this from happening?
Hm, I think I see where the problem lies:
struct D : B<D>, A { };
This way you inherit both a B<D> and a A instance. Effectively, this ressembles something like this:
struct D
{
B<D> implicitly_inherited_B_D;
A implicitly_inherited_A;
};
You now do the following:
D* d = new D();
void* v = d;
A* a = static_cast<A*>(v);
Problem is: v now points to the D instance, which shares its address with the inherited B<D> instance. But you cast the pointer back to A*, however, Ds A has an offset. So what you do corresponds to:
D* d = new D();
void* v = &d->implicitly_inherited_B_D;
A* a = static_cast<A*>(v);
// or equivalent:
A* aa = reinterpret_cast<A*>(&d->implicitly_inherited_B_D);
This is bound to fail...
If you want to cast back to A*, you need to make sure that your pointer actually points to the inherited A within D - which is quite easy:
D* d = new D();
void* v = static_cast<A*>(d);
// now this will work fine (v points to D's A part):
A* a = static_cast<A*>(v);
D* dd = static_cast<D*>(a); // even this one, original object was constructed as D
For comparison:
D* d = new D();
A* a = d;
D* ds = static_cast<D*>(a);
D* dr = reinterpret_cast<D*>(a); // actually undefined behaviour!!!
std::cout << d << std::endl << a << std::endl << ds << std::endl << dr << std::endl;
Assuming address of d is 0x10001000 and A within D has an offset of 8(sizeof(B<D> + possibly fill bytes for alignment), you'd see an output like this:
10001000
10001008
10001000
10001008
Note that the last line originates from the D* pointer received via reinterpret_cast!
Final note: Be aware that members can be rearranged - members declared first preceding members declared afterwards only is guaranteed for members within the same accessibility class (public/protected/private), between these sections, compiler is allowed to re-arrange. So in general you only can be safe if you go back from void* the same way you used for getting there:
void* v = d; // -> need to go back via static_cast<D*>!
A* a = static_cast<A*>(v); // requires v = static_cast<A*>(d);
B<D>* d = static_cast<B<D>*>(v); // requires v = static_cast<B<D>*>(d);
Anything else is undefined behaviour (be aware that the matter gets even worse as soon as virtual classes are involved, as then additionally there are the vtable pointers...).
If you cast a pointer to void * then always do the exact inverse cast when casting back to actual type.
So if you have :
D *d = new D;
void *v = d; // Here D* is casted to void *
When you get back the pointer, use the inverse cast. The following example are correct:
D *d2 = static_cast<D *>(v);
A *a2 = static_cast<D *>(v);
B<D> *b2 = static_cast<D *>(v);
Even better, if you can, try to avoid using void *. It can easily lead to hard-to-find bugs and this is even worst when using multiple inheritance.
If you have to use void *, then try do to it as locally as possible in the code so that ideally the conversion is done exactly at one place in the code for each direction.
class VoidMember
{
public:
void set(D *d) { v = d; }
D *get() { return static_cast<D *>(v);
private:
// In reality, you would not store a void like that but assume this is stored in
// a library / API that use `void *`
void *v;
};
While casting to other types might sometime works, it should be avoided as it make the code more fragile if code is refactored at some point like reordering base classes.

c++ Overload operator in abstract class

I have the folllowing interface:
class A
{
public:
virtual A * operator+(const A &rhs) const = 0;
}
And the abstract class :
class B : public A
{
public:
B(int val)
{
this->val = val;
}
virtual A * operator+(const A &rhs) const
{
return (new B(this->val + rhs.val));
}
int val;
}
Moreover, I have this class :
class C
{
public:
void add();
private:
std::stack<A *> Astack;
}
The operator+ prototype cannot be modified.
My issue is that I fails to create the add function. I tried this:
void C::add()
{
B first = *dynamic_cast<B *>(this->Astack.top()); // Error here
this->Astack.pop();
B second = *dynamic_cast<B *>(this->Astack.top()); // And here
this->Astack.pop();
B * res = first + second;
this->Astack.push(res);
}
But my compiler tells me :
error: cannot convert B to A * in initialization.
In fact, I fails to obtain to B to add them.
Operators cannot be virtual (well, technically they can, but it's a recipe for disaster, causing slicing, weird arithmetic expressions in client code and the unwarranted murder of cute baby seals).
Your C::add should look similar to this:
void C::add() // assuming implementation is supposed to sum instances and
// add replace the contents of Astack with the sum
{
A* x = Astack.top();
Astack.pop();
while(!Astack.empty()) {
A* y = Astack.top();
Astack.pop();
A* z = (*x) + (*y);
delete x;
delete y;
x = z; // latest result will be in x on the next iteration
}
Astack.push(x);
}
Also, your teacher should learn about not abusing memory allocation, not abusing virtual functions, not imposing virtual operators and good and bad practices in C++ class interface design - including the correct function signatures for overloading arithmetic operators).
first and second both are pointer variable and holding address. and you cant add two address.
first + second is not calling you operator overloading function, try by using *first + *second
B * res = first + second; // Error here !
Here you try to assign a A* pointer (which is returned by operator+) to a B* pointer. You have to cast the result. Something like that:
B * res = dynamic_cast<B*>(first + second);
Edit: not that you should use operator overloading in this way. utnapistim gave a good answer about that.

Increment value from void pointer

I'm trying to modify some variables [not necessary from the same class/struct] from keyboard's shortcuts, something like that:
A foo struct containing variables:
struct Foo {
int a;
float b;
};
struct Foo2 {
int c;
};
And a main like:
int main() {
Foo f;
Foo2 f2
void* p = &(f.a); //it could be &(f2.c)
if ('A' key activated) {
*p += 1;
}
}
Currently, I'm stucked at this point:
error: invalid operands to binary expression ('void' and 'int')
The only way to make it work is to change:
*p += 1;
By:
*(int*)p += 1;
Which is not a good solution, because I should not know the type pointed by p. Is there a way to do that?
Converting the pointer to void* lost the type information and the compiler will not know how to increment. Why don't you make a pointer to Foo instead?
int main() {
Foo f;
Foo* p = &f;
if ('A' key activated) {
p->a += 1;
}
}
Also keep in mind that incrementing a float is not a good idea!
For the quesion in the comment of this answer:
struct FooBar
{
int *a;
float *b;
};
int main() {
Foo f;
Bar b;
FooBar fb{&f.a, &b.b};
if ('A' key activated) {
*(fb.a) += 1;
}
}
Note that this solution is rather C-style. Look at lethal-guitar's answer for a more C++-style solution.
Edit: At first I didn't realize that you want to have different types per entry. Based on the task of handling keyboard shortcuts, you could use a polymorphic class, and put instances of it into a std::map:
class KeyHandler {
public:
virtual void onKeyStroke() = 0;
};
class MyHandler : public KeyHandler {
public:
MyHandler(int& value) : myValue(value) {}
virtual void onKeyStroke() {
myValue_ += 1;
}
private:
int& myValue_; // Other subclasses could have other data
};
// Now place instances of different Handlers into a std::map
typedef std::shared_ptr<KeyHandler> PKeyHandler;
std::map<char, PKeyHandler> bindings;
bindings['A'] = PKeyHandler(new IncrementIntHandler(&someInt));
bindings['B'] = PKeyHandler(new IncrementFloatHandler(&someFloat));
// The actual input handler then just invokes
// the correct handler for a key stroke.
bindings[keyCode]->onKeyStroke();
That way, you can define a handler class for every action you want to support, and implement the corresponding logic into these classes. You could make the base class' implementation just do nothing to handle non-mapped keys, etc.
Sure, use an int pointer instead:
int * p = &f.a;
if ( /* condition */ ) { ++*p; }

Are there practical uses for dynamic-casting to void pointer?

In C++, the T q = dynamic_cast<T>(p); construction performs a runtime cast of a pointer p to some other pointer type T that must appear in the inheritance hierarchy of the dynamic type of *p in order to succeed. That is all fine and well.
However, it is also possible to perform dynamic_cast<void*>(p), which will simply return a pointer to the "most derived object" (see 5.2.7::7 in C++11). I understand that this feature probably comes out for free in the implementation of the dynamic cast, but is it useful in practice? After all, its return type is at best void*, so what good is this?
The dynamic_cast<void*>() can indeed be used to check for identity, even if dealing with multiple inheritance.
Try this code:
#include <iostream>
class B {
public:
virtual ~B() {}
};
class D1 : public B {
};
class D2 : public B {
};
class DD : public D1, public D2 {
};
namespace {
bool eq(B* b1, B* b2) {
return b1 == b2;
}
bool eqdc(B* b1, B *b2) {
return dynamic_cast<void*>(b1) == dynamic_cast<void*>(b2);
}
};
int
main() {
DD *dd = new DD();
D1 *d1 = dynamic_cast<D1*>(dd);
D2 *d2 = dynamic_cast<D2*>(dd);
std::cout << "eq: " << eq(d1, d2) << ", eqdc: " << eqdc(d1, d2) << "\n";
return 0;
}
Output:
eq: 0, eqdc: 1
Bear in mind that C++ lets you do things the old C way.
Suppose I have some API in which I'm forced to smuggle an object pointer through the type void*, but where the callback it's eventually passed to will know its dynamic type:
struct BaseClass {
typedef void(*callback_type)(void*);
virtual callback_type get_callback(void) = 0;
virtual ~BaseClass() {}
};
struct ActualType: BaseClass {
callback_type get_callback(void) { return my_callback; }
static void my_callback(void *p) {
ActualType *self = static_cast<ActualType*>(p);
...
}
};
void register_callback(BaseClass *p) {
// service.register_listener(p->get_callback(), p); // WRONG!
service.register_listener(p->get_callback(), dynamic_cast<void*>(p));
}
The WRONG! code is wrong because it fails in the presence of multiple inheritance (and isn't guaranteed to work in the absence, either).
Of course, the API isn't very C++-style, and even the "right" code can go wrong if I inherit from ActualType. So I wouldn't claim that this is a brilliant use of dynamic_cast<void*>, but it's a use.
Casting pointers to void* has its importance since way back in C days.
Most suitable place is inside the memory manager of Operating System. It has to store all the pointer and the object of what you create. By storing it in void* they generalize it to store any object on to the memory manager data structure which could be heap/B+Tree or simple arraylist.
For simplicity take example of creating a list of generic items(List contains items of completely different classes). That would be possible only using void*.
standard says that dynamic_cast should return null for illegal type casting and standard also guarantees that any pointer should be able to type cast it to void* and back from it with only exception of function pointers.
Normal application level practical usage is very less for void* typecasting but it is used extensively in low level/embedded systems.
Normally you would want to use reinterpret_cast for low level stuff, like in 8086 it is used to offset pointer of same base to get the address but not restricted to this.
Edit:
Standard says that you can convert any pointer to void* even with dynamic_cast<> but it no where states that you can not convert the void* back to the object.
For most usage, its a one way street but there are some unavoidable usage.
It just says that dynamic_cast<> needs type information for converting it back to the requested type.
There are many API's that require you to pass void* to some object eg. java/Jni Code passes the object as void*.
Without type info you cannot do the casting.If you are confident enough that type requested is correct you can ask compiler to do the dynmaic_cast<> with a trick.
Look at this code:
class Base_Class {public : virtual void dummy() { cout<<"Base\n";} };
class Derived_Class: public Base_Class { int a; public: void dummy() { cout<<"Derived\n";} };
class MostDerivedObject : public Derived_Class {int b; public: void dummy() { cout<<"Most\n";} };
class AnotherMostDerivedObject : public Derived_Class {int c; public: void dummy() { cout<<"AnotherMost\n";} };
int main () {
try {
Base_Class * ptr_a = new Derived_Class;
Base_Class * ptr_b = new MostDerivedObject;
Derived_Class * ptr_c,*ptr_d;
ptr_c = dynamic_cast< Derived_Class *>(ptr_a);
ptr_d = dynamic_cast< Derived_Class *>(ptr_b);
void* testDerived = dynamic_cast<void*>(ptr_c);
void* testMost = dynamic_cast<void*>(ptr_d);
Base_Class* tptrDerived = dynamic_cast<Derived_Class*>(static_cast<Base_Class*>(testDerived));
tptrDerived->dummy();
Base_Class* tptrMost = dynamic_cast<Derived_Class*>(static_cast<Base_Class*>(testMost));
tptrMost->dummy();
//tptrMost = dynamic_cast<AnotherMostDerivedObject*>(static_cast<Base_Class*>(testMost));
//tptrMost->dummy(); //fails
} catch (exception& my_ex) {cout << "Exception: " << my_ex.what();}
system("pause");
return 0;
}
Please correct me if this is not correct in any way.
it is usefull when we put the storage back to memory pool but we only keep a pointer to the base class. This case we should figure out the original address.
Expanding on #BruceAdi's answer and inspired by this discussion, here's a polymorphic situation which may require pointer adjustment. Suppose we have this factory-type setup:
struct Base { virtual ~Base() = default; /* ... */ };
struct Derived : Base { /* ... */ };
template <typename ...Args>
Base * Factory(Args &&... args)
{
return ::new Derived(std::forward<Args>(args)...);
}
template <typename ...Args>
Base * InplaceFactory(void * location, Args &&... args)
{
return ::new (location) Derived(std::forward<Args>(args)...);
}
Now I could say:
Base * p = Factory();
But how would I clean this up manually? I need the actual memory address to call ::operator delete:
void * addr = dynamic_cast<void*>(p);
p->~Base(); // OK thanks to virtual destructor
// ::operator delete(p); // Error, wrong address!
::operator delete(addr); // OK
Or I could re-use the memory:
void * addr = dynamic_cast<void*>(p);
p->~Base();
p = InplaceFactory(addr, "some", "arguments");
delete p; // OK now
Don't do that at home
struct Base {
virtual ~Base ();
};
struct D : Base {};
Base *create () {
D *p = new D;
return p;
}
void *destroy1 (Base *b) {
void *p = dynamic_cast<void*> (b);
b->~Base ();
return p;
}
void destroy2 (void *p) {
operator delete (p);
}
int i = (destroy2 (destroy1 (create ())), i);
Warning: This will not work if D is defined as:
struct D : Base {
void* operator new (size_t);
void operator delete (void*);
};
and there is no way to make it work.
This might be one way to provide an Opaque Pointer through an ABI. Opaque Pointers -- and, more generally, Opaque Data Types -- are used to pass objects and other resources around between library code and client code in such a way that the client code can be isolated from the implementation details of the library. There are other ways to accomplish this, to be sure, and maybe some of them would be better for a particular use case.
Windows makes a lot of use of Opaque Pointers in its API. HANDLE is, I believe, generally an opaque pointer to the actual resource you have a HANDLE to, for example. HANDLEs can be Kernel Objects like files, GDI objects, and all sorts of User Objects of various kinds -- all of which must be vastly different in implementation, but all are returned as a HANDLE to the user.
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
/*** LIBRARY.H ***/
namespace lib
{
typedef void* MYHANDLE;
void ShowObject(MYHANDLE h);
MYHANDLE CreateObject();
void DestroyObject(MYHANDLE);
};
/*** CLIENT CODE ***/
int main()
{
for( int i = 0; i < 25; ++i )
{
cout << "[" << setw(2) << i << "] :";
lib::MYHANDLE h = lib::CreateObject();
lib::ShowObject(h);
lib::DestroyObject(h);
cout << "\n";
}
}
/*** LIBRARY.CPP ***/
namespace impl
{
class Base { public: virtual ~Base() { cout << "[~Base]"; } };
class Foo : public Base { public: virtual ~Foo() { cout << "[~Foo]"; } };
class Bar : public Base { public: virtual ~Bar() { cout << "[~Bar]"; } };
};
lib::MYHANDLE lib::CreateObject()
{
static bool init = false;
if( !init )
{
srand((unsigned)time(0));
init = true;
}
if( rand() % 2 )
return static_cast<impl::Base*>(new impl::Foo);
else
return static_cast<impl::Base*>(new impl::Bar);
}
void lib::DestroyObject(lib::MYHANDLE h)
{
delete static_cast<impl::Base*>(h);
}
void lib::ShowObject(lib::MYHANDLE h)
{
impl::Foo* foo = dynamic_cast<impl::Foo*>(static_cast<impl::Base*>(h));
impl::Bar* bar = dynamic_cast<impl::Bar*>(static_cast<impl::Base*>(h));
if( foo )
cout << "FOO";
if( bar )
cout << "BAR";
}

Can C++ template do this for conditions to improve code?

I want do this:
func(conditionA ? pa1 : pa2, conditionB ? pb1 : pb2, conditionC ? pc1 : pc2);
In C style function, there is no problem. But if func() is a template function, compiler will report errors.
Here pa1 and pa2, ... are different class and have a static method - "convert()". convert() is also declared as inline for performance consideration.
If template cannot solve this problem, there will be a very looooooooooong if-else like below.
if (conditionA)
{
typeA1 a;
if (conditionB)
{
typeB1 b;
if (conditonC)
{
C1 c;
Function(a, b, c);
}
else
{
C2 c;
Function(a, b, c);
}
}
else
{
typeB2 b;
if (conditonC)
{
C1 c;
Function(a, b, c);
}
else
{
C2 c;
Function(a, b, c);
}
}
}
else
{
typeA2 a;
if (conditionB)
{
typeB1 b;
if (conditonC)
{
C1 c;
Function(a, b, c);
}
else
{
C2 c;
Function(a, b, c);
}
}
else
{
typeB2 b;
if (conditonC)
{
C1 c;
Function(a, b, c);
}
else
{
C2 c;
Function(a, b, c);
}
}
}
The result of the conditional operator (that is, the a and b in p ? a : b) must be of the same type. That is, you can't do:
predicate() ? 3.14 : "sdfsd"
Make sure your pa1 and pa2 are compatible types (either they are the same type, inherit from one type, or are cast to compatible types). If you indeed have a convert member function that converts those types to compatible types, then why not just use:
conditionA ? pa1.convert() : pa2.convert()
Finally, it's not sooooo long. You already wrote out the definition. Just keep it generic and move on.
Make pa1 and pa2 inherit from a common base class, and use a reference to that ancestor as the argument type of your (then non-templated) function.
Your basic problem is that the type of an expression must be knowable at compile time.
Is the condition fixed and known at compile time? If so, it will be possible to use a metafunction to choose each parameter:
template <bool B>
struct choose {
typedef X type;
};
template <>
struct choose<false> {
typedef Y type;
};
...
func(choose<a_constant_bool_expr>::type());
(Simplified for a 1-parameter case; for 3 parameters you would define e.g. struct choose1, struct choose2, struct choose3.)
Otherwise, your best option is to derive all types from a common base as John Zwinck suggested. The only alternative to that is a gigantic switch statement or list of ifs.
Actually, maybe this is something that Boost.Variant would be good for?
The problem you have is with the strong typing at compile time and you wish to change the type at runtime. When the template for Function is compiled it needs to know what what types to provide for. You can use different types, you just can't do it all in 1 line.
Is it really that expensive to do a convert() that you would want to do it only if needed in Function?
Stepping away from template ...
Your description has made the length of the method worse than it might seem, you will need to have your a's b's and c's already defined. You could also reduce the conditions into a switch statement.
If you kept the a, b and c as a complete objects and could ask it for the value to be passed to the function.
class a {
p1, p2;
condition;
val value() { return condition? p1.convert, p2.convert };
}
You could make them have an interface that is common for those methods needed in the function. There are several ways to do this, but easiest is if you can change the class for TypeA1 etc. Adding a parent class of something like IConvertable here.
class IConvertable{
public:
~IConvertable(){}
virtual val convert() = 0;
}
And then implementing convert in each class to call the static version of convert.
It's a bit ugly, but you can turn your 3-level nesting into a single switch statement using bits:
const unsigned int caseA = 1 << 0;
const unsigned int caseB = 1 << 1;
const unsigned int caseC = 1 << 2;
switch ((conditionA ? caseA : 0) | (conditionB ? caseB : 0) | (conditionC ? caseC : 0)) {
case 0: func(pa2, pb2, pc2); break;
case caseA: func(pa1, pb2, pc2); break;
case caseB: func(pa2, pb1, pc2); break;
case caseA|caseB: func(pa1, pb1, pc2); break;
case caseC: func(pa2, pb2, pa1); break;
case caseA|caseC: func(pa1, pb2, pc1); break;
case caseB|caseC: func(pa2, pb1, pc1); break;
case caseA|caseB|caseC: func(pa1, pb1, pc1); break;
default: assert(false); // unreachable
}
This split your series of 3 binary decisions into a single 8-way decision, so it's simpler to reason about. Some people may hate it, but I find it quite readable.
Extending on (repeating) what everyone else has said...
This won't work:
template<class TYPE>
inline void Function( TYPE & object )
{
cout << "Function(): " << object.convert() << endl;
}
class A
{
public:
static const char * convert() { return "classA"; }
};
class B
{
public:
static const char * convert() { return "classB"; }
};
int
main(int argc)
{
A a;
B b;
Function( argc>1 ? a : b );
}
As a and b are different types, and the templated Function is being created for you based on the argument type.
But this WILL work:
template<class TYPE>
inline void Function( TYPE & object )
{
cout << "Function(): " << object.convert() << endl;
}
class C
{
public:
virtual const char * convert() = 0;
};
class A : public C
{
public:
static const char * staticConvert() { return "classA"; }
const char * convert() { return A::staticConvert(); }
};
class B : public C
{
public:
static const char * staticConvert() { return "classB"; }
const char * convert() { return B::staticConvert(); }
};
int
main(int argc)
{
A a;
B b;
Function( argc>1 ? (C&)a : (C&)b );
}
Though I really ought to use dynamic_cast...
Function( argc>1 ? dynamic_cast<C&>(a) : dynamic_cast<C&>(b) )