3

I have a template function which takes in objects. I need to determine whether the object is derived from a particular base class. If it is derived from the base class, I need to call additional function. Is there anyway I could do it in C++ Linux?

class baseA{
};

class derivedA:baseA{

};

class testB{
};

template<typename T>
void functionA(const T& value){

//if T is derived from baseA, call an additional function

//perform common operations for derivedA and testB...

}

To clarify, the additional function is a member function in derivedA but not in testB.

Steveng
  • 2,385
  • 6
  • 23
  • 20

6 Answers6

3

Boost.TypeTraits boost::is_base_of

const bool is = boost::is_base_of<Base,Derived>::value;

How does `is_base_of` work?

Community
  • 1
  • 1
2

It is somewhat difficult to mix templates and inheritance.

The trouble:

template <typename T>
void function(T const& t);

void function(A const& a);

If you use struct B: A {}:, then the template version is preferred, because no conversion is required, and it is therefore a "better" match.

If you have access to the definition of the template version, you can use a combination of is_base_of and disable_if.

template <typename T>
typename boost::disable_if< boost::is_base_of<A, T> >::type function(T const& t);

This simple modification makes use of SFINAE, basically it generates an error when trying to instantiate function for any class derived from A and the C++ standard specifies that if a function may not be instantiated then it is to be removed from the set of overloads considered without triggering a compiler error.

If you do not have access to the template definition of function, you're out of luck.

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
  • Isn't that supposed to be `boost::is_base_of::value`? – kirbyfan64sos Mar 07 '14 at 15:11
  • There is a difference between `boost::disable_if`, `boost::disable_if_c` and `std::enable_if`. The former expects a nested type named `type` whose inner `value` member should be `true` or `false` while the two latter expect a `bool` directly. So, normally, this answer is correct; and in terms of `std` it would be `template using disable_if = std::enable_if<!B, T>;` and `typename std::disable_if::value>::type` – Matthieu M. Mar 07 '14 at 15:16
  • Ack, you're right, I was thinking about `enable_if`. – kirbyfan64sos Mar 07 '14 at 15:19
1

You can use Run Time Type Identification (RTTI) for this purpose. An Example follows:

class A{
public:
virtual void func(){cout << "Base" << endl;}
virtual ~A(){}
};

class B:public A{
public:
void func(){cout << "Derived" << endl;}
};

int main(){
A * d1 = new B();
B * d2;

d1 -> func() ;

d2 = dynamic_cast<B*>(d1);

if(d2 != NULL)
       cout << "Base exists" << endl;
else
       cout << "No relation" << endl;

return 0;
}
Arunmu
  • 6,837
  • 1
  • 24
  • 46
0

Without knowing the exact nature of the additional work you want to do, there could be 2 ways might approach this.

Option 1: Say the function you want to call is foo(). You could implement foo() on both baseA and testB. baseA::foo() can give you your extra work while testB:foo() would just do nothing. But this style wouldn't make sense if foo() doesn't belong in either of those 2 classes.

Optional 2: Specialize functionA for baseA (or optionally testB as well)

void function_specialized(baseA* param)
{
    // Do your extra work

    // Then call the common functionA
    functionA<baseA>(*param);
}

template<typename T>
functionA(const T& value)
{
   //...
}
Sonny Saluja
  • 7,193
  • 2
  • 25
  • 39
0

A true template specialization would be even better :)

class A {
public:
    char c;
};

template <typename T> void foo(const T & t)
{
    std::cout << "this is generic.";
}

template <> void foo(const A & a)
{
    std::cout << "this is specialized.";
}

int main(int argc, char * argv[])
{
    foo(A());

    foo(int());
}
MatiasFG
  • 576
  • 2
  • 8
  • 2
    Would it, really ? The question is about using `B b; foo(b);` where `struct B: A {};`, in your case I highly suspect that the generic version will be called. – Matthieu M. Dec 17 '10 at 07:34
  • You are right, my code only works for class A... the template specialization does not apply for derived classes of A. Sorry! – MatiasFG Jan 11 '11 at 16:11
-1

You can do template specialization which will be fully static:

template <typename T>
void function(const T& value)
{
  common_task();
}

template <>
void function<A>(const A& value)
{
  common_task();
  // special A tasks
}
Julio Guerra
  • 5,523
  • 9
  • 51
  • 75