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

2020-08-17 17:26发布

问题:

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?

回答1:

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.



回答2:

#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{});
}


回答3:

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



回答4:

C++11+ :

#include <type_traits> // for is_base_of<>

class Base {};
class Derived : public Base {};

class NotDerived {};

template<typename Class>
void foo(const Class& cls)
{
  static_assert(is_base_of<Base, Class>::value, "Class doesn't inherit from Base!");
  // The codes...
}

int main()
{
  foo(Derived()); // OK!
  foo(NotDerived()); // Error!

  return 0;
}