generic interface

Consider the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class A {};

class B : public A{

int b;
};

class C : public A{

int c;
};

template <class T, class Y> //generic function
foo(T TestObject)// TestObject could be an instance of B or C or any other //classes which it is inherited from A. The inherited classes has only one //member from the type integer. 
{


Y IntegerVarValue = TestObject.IDENTIFIER; // here is the problem. How could I //know the identifier name of the member variable? 
}

Since the testObject is declared and passed as function argument, how can I get access to its member variable despite I do not know its identifier name //and know only its data type, in this case an integer, because the function is generic and I do not know how many classes will be inherited from A, but I only know that the inherited classes has only one member variable from one specific data type.
I appreciate any suggestion...
Last edited on
B and C can have get/set member functions with the same name that you use in foo.

You probably don't need to use both inheritance and templates here. If you use templates you don't need the class A.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class B{
public:
	int get() const {return b;}
private:
	int b;
};

class C{
public:
	int get() const {return c;}
private:
	int c;
};

template <class T, class Y> //generic function
void foo(T TestObject)
{
	Y IntegerVarValue = TestObject.get();
}
That could be a good solution. However, suppose we have a parent class which we have to inherit from, given from one vendor, and there are rules how to extend the child classes. If you are not allowed to implement such member function. How could you access the member variables as described above?
If A has virtual functions to get the child members maybe you can use them but then I don't think you need templates.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class A
{
public:
	virtual int get() const = 0;
};

class B : public A{
public:
	virtual int get() const {return b;}
private:
	int b;
};

class C : public A{
public:
	virtual int get() const {return c;}
private:
	int c;
};

void foo(A& TestObject)
{
	int IntegerVarValue = TestObject.get();
}
There is no way to get access a variable without knowing its name.
This is poor use of templates. What you need is a better structure with some sort of common interface. Either add int member to A or a virtual get, as Peter suggested.
It is really irrelevant for this particular problem that B, C etc. are derived from a common base class.

One possibility is to give the member variable the same identifier (name) in each class.

If that is not possible, a non-intrusive way (ie. one that does not require any modification of these classes) is to write an external accessor function which is overloaded or specialized for each derived class.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>

struct A {};

struct B : A { int b = 5 ; }; 

struct C : A { int c = -9 ; };

template < typename T > int accessor( const T& object ) ; // generalization is not defined

template< typename T > void foo( T& object )
{
    int value = accessor(object) ;
    std::cout << value << '\n' ; // use value
}

int accessor( const B& object ) { return object.b ; }
int accessor( const C& object ) { return object.c ; }

int main()
{
    B b ;
    C c ;
    foo(b) ;
    foo(c) ;
}



Or perhaps use The Type Traits Introspection Library (boost sandbox)
http://svn.boost.org/svn/boost/sandbox/tti/libs/tti/doc/html/index.html
Topic archived. No new replies allowed.