C ++ приведение шаблонного класса - PullRequest
1 голос
/ 30 октября 2010

У меня вопрос по шаблонам. Я хотел бы иметь шаблонный класс, который содержит, скажем, массив чисел с плавающей или двойной точностью.

Я могу написать функцию clone (), которая дублирует ее. Нет проблем. Тем не менее, я хотел бы иметь другую функцию под названием cast (), которая выполняет перевод туда и обратно между double и float. Это уже несколько обсуждалось, но я не думаю, что проблема та же:

stackoverflow.com / вопросы / 714213 / C-шаблон для литья под давлением

У меня проблема с ошибкой компилятора, а не с компоновщиком. Сообщение об ошибке:

main.cpp: In function `void caster()':
main.cpp:63: error: expected primary-expression before "double"
main.cpp:63: error: expected `;' before "double"
main.cpp:64: error: expected primary-expression before "float"
main.cpp:64: error: expected `;' before "float"
main.cpp:65: error: expected primary-expression before '>' token
main.cpp:65: error: expected primary-expression before ')' token

Я сбросил код ниже. В строках 63, 64 и 65 я прокомментировал «Ошибка здесь».

Кстати, мой компилятор "GNU C ++ версии 3.4.5 20051201 (Red Hat 3.4.5-2) (x86_64-redhat-linux) скомпилирован GNU C версии 3.4.5 20051201 (Red Hat 3.4.5- 2)».

После некоторого поиска в Google оказывается, что кто-то уже испытывал эту проблему:

gcc.gnu.org / мл / НКУ-помощь / 2006-04 / msg00022.html

Здесь есть решение:

gcc.gnu.org / мл / НКУ-помощь / 2006-04 / msg00023.html

Но когда оригинальный постер спрашивает, как почему это работает, ответ не очень ясен:

gcc.gnu.org / мл / НКУ-помощь / 2006-04 / msg00025.html

К сожалению, ссылка мертва, и у меня нет третьего издания Страуструпа. Теперь у меня есть исправление, мой код работает. Но, Stackoverflow, почему это работает?


#include <stdio.h>

// =================== This would be the header ===================
template <class T>
class foo
{
public:
             foo(const T val) {d_data = new double; *d_data = val;}
    virtual ~foo() {delete d_data;};

    foo* clone() const;

    template<class U>
    foo<U>* cast() const;

private:
    double *d_data;
};

// =================== This would be the implementation of the class ===================
template<class T>
foo<T>* foo<T>::clone() const
{
    return new foo<T>(*d_data);
}

template<class T>
template<class U>
foo<U>* foo<T>::cast() const
{
    return new foo<U>(*d_data);
}

template class foo<float>;
template class foo<double>;

template foo<float>* foo<float>::cast() const;
template foo<float>* foo<double>::cast() const;
template foo<double>* foo<float>::cast() const;
template foo<double>* foo<double>::cast() const;

// =================== Using the class ===================
template <class T>
void caster()
{
    foo<double> *f1 = NULL;
    foo<float>  *f2 = NULL;
    foo<T>      *f3 = NULL;

    // I am looking at something that compiles
    // I don't care about linking for now
    // This will crash at runtime because of
    // NULL, but that's just an example

    f1->cast<double>(); // compiler OK
    f1->cast<float>();  // compiler OK
    f1->cast<T>();      // compiler OK

    f2->cast<double>(); // compiler OK
    f2->cast<float>();  // compiler OK
    f2->cast<T>();      // compiler OK

    f3->cast<double>(); // Error here
    f3->cast<float>();  // Error here
    f3->cast<T>();      // Error here

    f3->foo<T>::template cast<double>(); // It works!
    f3->foo<T>::template cast<float>();  // It works!
    f3->foo<T>::template cast<T>();      // It works!
}

int main(int argc, char **argv)
{
    return 0;
}

1 Ответ

4 голосов
/ 30 октября 2010
f3->cast<double>(); // Error here 

В этой строке компилятор не знает, должен ли < после f3->cast означать начало аргументов шаблона или он меньше оператора сравнения.

Toявно указать, что он обозначает начало аргумента шаблона.Правильный путь:

f3->template cast<double>();

Таким образом, обозначение .template (и аналогичные обозначения, такие как ->template) следует использовать только внутри шаблонов и только в том случае, если они следуют тому, что зависит от параметра шаблонанапример выражение f3, которое зависит от параметра шаблона T)

...