"шаблонный полиморфизм" при вызове функции для шаблонного параметра базового типа с производным типом? - PullRequest
3 голосов
/ 02 июля 2011

У меня есть шаблон класса:

template <class T>
class TemplateClass
{
   //irrelevant what this class does
}

И два класса, один базовый и один класс, производный от него:

class Base
{
    //does whatever
}

class Derived : public Base
{
}

Теперь я хочу собрать функцию, которая может работать с TemplateClass шаблонного типа Base *, а также TemplateClass шаблонного типа Derived * без необходимости реализации функции отдельно для обоих типов.

В коде это то, что я хотел бы сделать:

void DoSomething(const TemplateClass<Base *> &tc)
{
   //do something
}

И еще где-то в коде:

TemplateClass<Base *> a;
TemplateClass<Derived *> b;

DoSomething(a); //Works
DoSomething(b); //Doesn't work, but I'd like it to work

Есть ли способ реализовать это без необходимости ручной перегрузки DoSomething for Derived *?

Ответы [ 2 ]

5 голосов
/ 02 июля 2011

К сожалению, C ++ не поддерживает ковариацию шаблонов, поэтому вы не можете сделать это автоматически.В качестве обходного пути вы можете сделать что-то вроде этого:

template <typename T>
void DoSomething(const TemplateClass<T*>& tc) {
    // in C++03, use BOOST_STATIC_ASSERT and boost::is_convertible
    static_assert(
        std::is_convertible<T*, Base*>::value,
        "Template argument must be convertible to Base*"
    );

    // ...
}

Демонстрация на ideone .

0 голосов
/ 02 июля 2011

Это легко решить, если вы не против более общей ситуации:

Я бы просто добавил параметр шаблона в вашу DoSomething функцию:

template<class T>
void DoSomething(const TemplateClass<T *> &tc)
{
}

Конечно, это не позволяет вам напрямую ограничить параметр T в качестве подкласса Base. Но это позволит вам не записывать несколько перегрузок DoSomething.

Редактировать

Если ваш TemplateClass был предназначен для переноса значения типа T, то может быть способ ограничиться параметром для DoSomething.

Предположим, TemplateClass было объявлено что-то вроде

template<class T>
class TemplateClass
{

public:

    TemplateClass( T value )
    : Value(value)
    {
    }

    T Value;
};

Тогда DoSomething можно записать как

template<class T>
void DoSomething( const TemplateClass<T *> &tc )
{
    Base * b = tc.Value;
}

Теперь во время компиляции строка Base * b = tc.Value будет компилироваться, только если для T установлен подкласс Base. В противном случае произойдет сбой из-за недопустимого преобразования.

Конечно, это очень простой пример, который может игнорировать некоторые элементы хорошего дизайна. Но принцип там, и это единственный способ, которым я в настоящее время знаю о создании такого ограничения для параметра шаблона.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...