Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ template function for derived class with std::is_base_of

I've got problem with creating function that for given type, if it's derived from other one do something and for all other cases do something other. My code:

class BaseClass {};
class DerivedClass : public BaseClass {};

template <typename T>
void Function(typename std::enable_if<std::is_base_of<BaseClass, T>::value, T>::type && arg) {
    std::cout << "Proper";
}

template <typename T>
void Function(T && arg) {
    std::cout << "Improper";
}

void test() {
    Function(DerivedClass{});
}

For class DeriviedClass and other based on BaseClass I'd like to call function couting Proper, but it couts Improper. Any suggestions?

like image 540
miqelm Avatar asked Feb 07 '17 08:02

miqelm


People also ask

Can a template base class derived?

It is possible to inherit from a template class. All the usual rules for inheritance and polymorphism apply. If we want the new, derived class to be generic it should also be a template class; and pass its template parameter along to the base class.

Is C++ a base class?

Difference between Base class and Derived class in C++ Base Class: A base class is a class in Object-Oriented Programming language, from which other classes are derived. The class which inherits the base class has all members of a base class as well as can also have some additional properties.

How do you define a template function in C++?

Defining a Function TemplateA function template starts with the keyword template followed by template parameter(s) inside <> which is followed by the function definition. In the above code, T is a template argument that accepts different data types ( int , float , etc.), and typename is a keyword.

What is Typename C++?

" typename " is a keyword in the C++ programming language used when writing templates. It is used for specifying that a dependent name in a template definition or declaration is a type.


3 Answers

As mentioned in the comments to the question, SFINAE expressions won't work the way you did it.
It should be instead something like this:

template <typename T>
typename std::enable_if<std::is_base_of<BaseClass, T>::value>::type
Function(T && arg) {
    std::cout << "Proper" << std::endl;
}

template <typename T>
typename std::enable_if<not std::is_base_of<BaseClass, T>::value>::type
Function(T && arg) {
    std::cout << "Improper" << std::endl;
}

SFINAE expressions will enable or disable Function depending on the fact that BaseClass is base of T. Return type is void in both cases, for it's the default type for std::enable_it if you don't define it.
See it on coliru.

Other valid alternatives exist and some of them have been mentioned in other answers.

like image 184
skypjack Avatar answered Sep 27 '22 20:09

skypjack


#include <typeinfo>
#include <iostream>

class BaseClass {};
class DerivedClass : public BaseClass {};
class OtherClass {};

template <typename T,typename = typename std::enable_if<std::is_base_of<BaseClass, T>::value, T>::type>
void Function(T && arg)
{
  std::cout << "Proper" << std::endl;
}

void Function(...)
{
  std::cout << "Improper"<< std::endl;
}

int main()
{
  Function(DerivedClass{});
  Function(BaseClass{});
  Function(OtherClass{});
}
like image 20
user5821508 Avatar answered Sep 27 '22 20:09

user5821508


template <typename T>
auto Function(T && arg) -> typename std::enable_if<std::is_base_of<BaseClass, T>::value>::type 
{
    std::cout << "Proper";
}

template <typename T>
auto Function(T && arg) -> typename std::enable_if<!std::is_base_of<BaseClass, T>::value>::type 
{
    std::cout << "Improper";
}

wandbox example

like image 21
Vittorio Romeo Avatar answered Sep 27 '22 20:09

Vittorio Romeo