2016-03-29 2 views
1

из кода ниже, я получаю следующий результат:Переключения между специализацией и перегрузками

Вызова member_function

производного член функции

Вызова template_function

шаблонной функция

Производная функция-член

Как и ожидалось, специализация template_function не вызывается здесь, потому что производный имеет тип Base *, но вызывается правильная версия member_function.

Однако иногда бывает полезно вызвать функции не-члена в функциях шаблона.

Существует ли способ гарантировать, что специализированная версия функции шаблона будет вызываться, когда динамические экземпляры класса Derived объявляются как имеющие тип Base *?

Спасибо!

#include <iostream> 

// Base and Derived classes 

class Base 
{ 
    public: 
     virtual void member_function() const 
     { std::cout << "Base member function" << std::endl; }; 
}; 

class Derived : public Base 
{ 
    public: 
     virtual void member_function() const 
     { std::cout << "Derived member function" << std::endl;}; 
}; 


// Functions 

template<typename T> 
void template_function(T const & arg) 
{ 
    std::cout << "template function" << std::endl; 
    arg.member_function(); 
} 

template<> 
void template_function(Derived const & arg) 
{ 
    std::cout << "Specialized function" << std::endl; 
    arg.member_function(); 
} 


// Main 

int main() 
{ 
    Base * derived = new Derived();; 

    std::cout << "Call member_function" << std::endl; 
    derived->member_function(); 

    std::cout << std::endl; 

    std::cout << "Call template_function" << std::endl; 
    template_function(*derived); 

} 
+0

Посмотрите на [Visitor_pattern] (https://en.wikipedia.org/wiki/Visitor_pattern) – Jarod42

+1

Это непонятно, о чем вы спрашиваете. Какую проблему ты пытаешься решить? – Barry

+0

Спасибо, Джаррод. Илл будет смотреть на шаблон посетителя. – Aleph

ответ

1

Вы можете добавить два шаблона template_function что вы enable_if на std::base_of<T, Derived>, как этот

// Functions 
template<typename T, std::enable_if_t<not std::is_base_of<T, Derived>::value>* = nullptr> 
void template_function(T const & arg) 
{ 
    std::cout << "template function" << std::endl; 
    arg.member_function(); 
} 

template<typename T, std::enable_if_t<std::is_base_of<T, Derived>::value>* = nullptr> 
void template_function(T const & arg) 
{ 
    std::cout << "Specialized function" << std::endl; 
    arg.member_function(); 
} 


// Main 

int main() 
{ 
    Base const * base = new Base(); 
    Base const * derived = new Derived(); 

    std::cout << "Call member_function" << std::endl; 
    base->member_function(); 
    derived->member_function(); 

    std::cout << std::endl; 

    std::cout << "Call template_function" << std::endl; 
    template_function(*base); 
    template_function(*derived); 

} 

Live Example.

В качестве альтернативы, и гораздо проще, вы можете просто добавить template_function(Base const&) перегрузки

// Functions 
template<typename T> 
void template_function(T const & arg) 
{ 
    std::cout << "template function" << std::endl; 
    arg.member_function(); 
} 

void template_function(Base const & arg) 
{ 
    std::cout << "Specialized function" << std::endl; 
    arg.member_function(); 
} 

Live Example