2016-06-23 3 views
4

У меня есть этот исходный код, который позволяет мне бросить Point<float> в Point<double>:C++ Cast Шаблон

template<class T> struct Point{ 
    template <typename NewType> Point<NewType> cast() const{ 
     return Point<NewType>(); 
    }  
}; 

int main(){ 
    Point<float> p1; 
    Point<double> p2; 
    p2 = p1.cast<double>(); 

    return 0; 
} 

Этот исходный код компилирует хорошо. Теперь я добавляю следующий класс и у меня есть ошибки компиляции на линии, которая делает бросок: ошибка

template <class T> struct PointContainer{ 
    void test(){ 
     Point<T> p1; 
     Point<double> p2; 
     p2 = p1.cast<double>(); //compilation error 
    } 
}; 

компиляции: error: expected primary-expression before ‘double’.

Почему я получаю эту ошибку и как ее решить?

+3

Связанный: http://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords?rq=1 ("* "template" keyword * ") – melpomene

ответ

0

Принятый ответ в сообщении, связанный с сообщением, содержит ответ.

Необходимо использовать ключевое слово template.

template <class T> struct PointContainer{ 
    void test(){ 
     Point<T> p1; 
     Point<double> p2; 
     p2 = p1.template cast<double>(); 
    } 
}; 
4

Point<T> является зависимым именем (это зависит от параметра шаблона T), так что компилятор не знает, что Point<T>::cast является:

  • Point<T>::cast может быть атрибута, то p1.cast < будет рассматриваться как сравнение с тем, что будет дальше.
  • Point<T>::cast может быть шаблоном (ваш случай).

Поскольку компилятор не может знать, он предполагает первый, следовательно, вашу ошибку (вы не можете сравнивать что-то с типом). Чтобы решить эту проблему, необходимо явно указать компилятору, что p1.cast является шаблонный метод:

p2 = p1.template cast<double>(); 

Для получения дополнительной информации см этот вопрос: Where and why do I have to put the "template" and "typename" keywords?

8

Короткий ответ: вам нужно добавить ключевое слово template сразу после оператор доступа члена (точка) в строке, которая дает вам ошибку.

Длинный ответ: в PointContainer<T>, T - неизвестная переменная шаблона. Поскольку в C++ шаблоны могут иметь специализации, которые могут полностью отличаться от базового шаблона, компилятор не знает, имеет ли тип Point<T> листинг членов, который является шаблоном функции, перед заменой T для фактического типа. Вот почему вы можете использовать листинг в основном: Point<float> - это конкретный тип, и компилятор знает, что он имеет этот шаблон функции.

Поскольку компилятор не знает тип члена, который будет «отличать», он не позволяет использовать операции, предполагающие, что это тип, шаблон или и то, и другое. Для этого вам нужно сообщить это компилятору, используя ключевые слова typename и template.Представьте себе, что в дополнении к шаблонной функции cast есть typedef T value_type в Point<T>:

Point<float>::value_type f = 1.0f; // OK 
Point<T>::value_type f = 1.0f; // Bad, compiler does not identify that as a type 
typename Point<T>::value_type f = 1.0f; // OK 

Point<float> pf; 
Point<T> pT; 
Point<double> pd1 = pf.cast<double>(); // OK 
Point<double> pd2 = pT.cast<double>(); // Bad, compiler does not know cast is a template 
Point<double> pd3 = pT.template cast<double>(); // OK 
0

Как все остальные уже сказал, ваша проблема в том, что вам нужно, чтобы сообщить компилятору, что зависимые шаблоны шаблоны с раздражающим использованием из ключевое слово template.

y=x.template cast<Y>(); 

Путь вокруг этого заключается в том, чтобы сделать его более не зависимым от шаблона.

Самого простой способ, чтобы написать свободную функцию

template<class D, class S> 
Point<D> cast(Point<S> const& s){ return s.template cast<D>(); } 

Теперь вы можете свободно использовать:

y = cast<Y>(x); 

без раздражающего template ключевого слова, потому что тот факт, что cast шаблона больше не зависимый.