JoJo
JoJo

Reputation: 1447

Does C++ 11 support template class reflection?

I know a little knowledge about C++ 11 template. My intention is to have a template function as shown below:

template<class T>
void function(T * a) {
  if (T belongs to class M) {
    a->function_m();
  } else {
    a->function_o();
  }
}

Does C++ 11 support this template class reflection?

Upvotes: 4

Views: 1641

Answers (4)

pPanda_beta
pPanda_beta

Reputation: 648

What u want can be done in c++17

template <typename T>
void function( T* a )
{
    if constexpr (std::is_base_of<M,T>::value)
        a->function_m();
    else
        a->function_o();
}

Full example : http://melpon.org/wandbox/permlink/MsHnYQNlBcRhTu2C As referred by @Fabio Fracassi

Upvotes: 0

bku_drytt
bku_drytt

Reputation: 3249

Yes, and better yet, you don't need to perform if(...){} else{} statements to do so. You can use tag dispatching or specializations to avoid the conditional statements. The following example uses tag dispatching.

Example:

#include <iostream>
#include <type_traits>

template <typename B, typename D>
void function( D* a )
{
    function( a, typename std::is_base_of<B, D>::type{} );
}

template <typename T>
void function( T* a, std::true_type )
{
    a->function_b();
}

template <typename T>
void function( T* a, std::false_type )
{
    a->function_c();
}

struct B
{
    virtual void function_b() { std::cout << "base class.\n"; }
};

struct D : public B
{
    void function_b() override { std::cout << "derived class.\n"; }
};

struct C
{
    void function_c() { std::cout << "some other class.\n"; }
};

int main()
{
    D d;
    C c;
    function<B, D>( &d );
    function<B, C>( &c );
}

This mechanism does not require both functions to be visible in the same scope.

Upvotes: 5

Jarod42
Jarod42

Reputation: 217970

Several choices:

  • SFINAE:

    template<class T>
    std::enable_if_t<std::is_base_of<M, T>>
    function(T* a)
    {
        a->function_m();
    }
    
    template<class T>
    std::enable_if_t<!std::is_base_of<M, T>>
    function(T* a)
    {
        a->function_o();
    }
    
  • or tag dispatching:

    namespace details {
        template<class T>
        void function(T* a, std::true_type) {
            a->function_m();
        }
    
        template<class T>
        void function(T* a, std::false_type) {
            a->function_o();
        }
    }
    template<class T>
    void function(T* a)
    {
        details::function(a, std::is_base_of<M, T>{});
    }
    

Upvotes: 3

Vaughn Cato
Vaughn Cato

Reputation: 64308

Yes, std::is_base_of<Base,Derived>:

template<class T>
void function(T * a) {
  if (std::is_base_of<M,T>::value) {
    a->function_m();
  } else {
    a->function_o();
  }
}

However, it is likely to cause a problem in this case, since function_m() and function_o() would both need to be callable.

Upvotes: 1

Related Questions