简体   繁体   中英

Template type check C++

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.

Boost.TypeTraits boost::is_base_of

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

How does `is_base_of` work?

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.

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;
}

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)
{
   //...
}

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());
}

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
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM