Проблема с шаблонами C ++ - PullRequest
       4

Проблема с шаблонами C ++

1 голос
/ 18 декабря 2011

Я столкнулся с большой проблемой (по крайней мере, для меня) в отношении создания и наследования шаблонов. Давайте посмотрим этот код:

class Convertible
{
    public:

    template<class T>
    T* AsPtrTo()
    {
        return reinterpret_cast<T*>(this);
    }
};

template<class T>
class TemplateBase : public Convertible
{
};

template<class T>
class TemplateDerived : public TemplateBase<T>
{
    public:

    void Method1(TemplateBase<T> t)
    {
        t.AsPtrTo<int>(); // <<<<<< ERROR
    }
};


int main()
{
    TemplateDerived<int> d;
    TemplateBase<int> b;
    d.Method1(b);

    return 0;
}

Как видите, существует класс с именем Convertible, имеющий только один метод шаблона, который выполняет приведение типов. Существует также шаблонный класс, который наследуется от Convertible, а затем еще один шаблонный класс, который наследуется от предыдущего. Этот последний класс шаблона реализует метод, который использует метод шаблона AsPtrTo, который должен быть унаследован от Convertible и создан во время компиляции для типа T, используемого в основной функции.

По какой-то причине я не могу понять, это терпит неудачу. GCC 4.4.1 дает мне это сообщение:

ошибка: ожидаемое первичное выражение перед 'int'

Я отметил строку ошибки.

Я подумал, что, может быть, кто-то из экспертов С ++ сможет мне помочь.

Спасибо всем заранее!

Ответы [ 2 ]

6 голосов
/ 18 декабря 2011

Вам необходимо использовать ключевое слово template как:

 t.template AsPtrTo<int>(); 

Это обсуждалось так много раз, что вы найдете бесчисленное количество сообщений на SO.

Но здесь вы найдете одно из лучших объяснений:

4 голосов
/ 18 декабря 2011

Попробуйте:

void Method1(TemplateBase<T> t)
{
    t.template AsPtrTo<int>();
}

Причина в том, что компилятор не знает, какие функции-члены t имеют во время разбора, поэтому он не знает, является ли AsPtrTo функцией шаблона илине.Из-за этого он не может правильно проанализировать его без подсказки.

В качестве примера того, почему это необходимо, рассмотрим следующий код:

struct Foo
{
    template<int N> int foo(int x) { return x + N; }
};

struct Bar
{
    int foo;
}; 

template <typename T>
int baz(T t)
{
    return t.foo<0>(1);
}

На первый взгляд выглядитвроде бы baz<Foo> сработало бы, но baz<Bar> не сработало бы, но все наоборот!

Подумайте, что произойдет, если я позвоню baz<Bar>

return t.foo<0>(1);

foo является переменной-членом, поэтому, когда он видит <, он думает, что это оператор меньше чем, поэтому он анализирует выражение следующим образом:

return (t.foo < 0) > (1);

Что является допустимым выражением (после некоторых неявных преобразований в / из bool)!

Дело в том, что оно анализирует выражение как для Foo, так и для Bar, поэтому template ключевое слово необходимо.Компиляторы должны исходить из того, что это не функция-член шаблона (если вы не добавите туда это ключевое слово).

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