Шаблонный класс C ++ и тип возвращаемого значения как ограничение - PullRequest
2 голосов
/ 10 октября 2011

Извините за этот глупый вопрос, но я совсем новичок в C ++.

У меня есть базовый класс с именем AlertInfoBase в моем проекте.У него есть несколько десятков подклассов.Теперь я хочу иметь шаблон класса, который будет иметь метод filter().Этот метод всегда возвращает ссылку на AlertInfoBase.Вот код:

template <class T>
class AlertInfoFilter
{
public:
    AlertInfoFilter() { }
    AlertInfoBase & filter(T & alertInfo)
    {
        return alertInfo;
    }
};

Как видите, фильтр методов просто возвращает переданный параметр.Моя цель - создать альтернативные реализации filter(), используя специализацию шаблонов, но сейчас это не моя проблема / вопрос.Странная вещь, с которой я сталкиваюсь, заключается в том, что, когда я передаю экземпляр класса в filter(), который находится в подклассе от AlertInfoBase, все работает как ожидалось.Он возвращает ту же ссылку, но когда я передаю экземпляр класса, который не реализует AlertInfoBase, проект не компилируется.На самом деле, я хочу иметь такое поведение, но некоторые пояснения, почему это происходит, было бы неплохо.Достаточно ли умен компилятор, чтобы предположить, что я заполняю метод неверным параметром из-за типа возвращаемого значения?

Спасибо

PS Я использую компилятор MinGW.

Ответы [ 4 ]

5 голосов
/ 10 октября 2011

Вы можете думать о шаблонах как о механизме генерации кода.Конкретная реализация шаблона в большинстве случаев идентична написанному вручную коду, который просто заменял аргумент шаблона, где это необходимо.В вашем примере, если вы создали экземпляр AlertInfoFilter с std::string (как пример класса, который не наследует от AlertInfoBase), то будет сгенерирован (приблизительно) следующий код:

class AlertInfoFilter_string
{
public:
    AlertInfoFilter_string() { }
    AlertInfoBase & filter(std::string & alertInfo)
    {
        return alertInfo;
    }
};

Ясно, что это не должно компилироваться.

4 голосов
/ 10 октября 2011

Да, компилятор достаточно умен, чтобы это понимать.Он использует неявное преобразование из дочернего в базовый класс, когда T спускается с AlertInfoBase и не может преобразовать ваш T в возвращаемый тип в других случаях.

Это также будет работать с классом, которыйреализован operator AlertInfoBase& в несвязанном классе, но это только добавит путаницу, поэтому я не предлагаю этого.

0 голосов
/ 10 октября 2011

На самом деле компилятор делает что-то очень близкое к тому, чтобы взять код, подставив T для фактического аргумента и скомпилировав шаблон.Это происходит один раз для каждого отдельного T, который вы используете в своей программе.

Когда вы передаете, например.int, вы получите:

class AlertInfoFilter
{
public:
    AlertInfoFilter() { }
    AlertInfoBase & filter(int & alertInfo)
    {
        return alertInfo;
    }
};

, что явно не компилируется.

0 голосов
/ 10 октября 2011

filter принимает T в качестве ввода и преобразует его в AlertInfoBase.Если T теперь является типом, который не является подклассом AlertInfoBase и не предлагает преобразование, то программа не может быть скомпилирована.

...