Problem przy kompilacji klasy szablonowej.

0

Cześć, nie mogę znaleźć błędu w następującym kodzie:
Polynominal.h:

#pragma once
#include <vector>

template <typename T> // T can be int, double or float
class Polynomial
{
private:
	// degree is a vector.size() - 1, so if we have vector [1, 4, 5, 0 , 2] <==> x^4 + 4x^3 + 5x^2 + 2
	// the biggest deegree is at the [0] index
	std::vector<T> factors;
public:
	Polynomial();
	Polynomial(const std::vector<T>& factors);
	Polynomial(const Polynomial<T>& poly);
	~Polynomial();
	template < typename Z>
	double operator()(T x);
};

Polynominal.cpp:

#include "Polynomial.h"


template <typename T>
Polynomial<T>::Polynomial()
{
	factors.assign(1, 0);
}

template<typename T>
Polynomial<T>::Polynomial(const std::vector<T>& factors) : factors(factors) {}

template<typename T>
Polynomial<T>::Polynomial(const Polynomial<T>& poly) : factors(poly.factors) {}


template <typename T>
Polynomial<T>::~Polynomial() {}

template<typename T>
template<typename Z>
double Polynomial<T>::operator()(T x)
{
	if (factors.size() == 1)
		return factors[0];
	else if (factors.size() == 2)
		return factors[0] * x + factors[1];
	double sum = factors[0]*x + factors[1];
	for (int i = 2; i < (int) factors.size() ; i++ )
	{
		sum = sum * x + factors[i];
	}
	return sum;
}

main.pp:

#include <iostream>
#include "Polynomial.h"

int main()
{
	std::vector<double> vec(4, 1);
	Polynomial<double> forthDegree(vec);
}

Błędy zaczyna wywalać przy delkaracji obiektu Polynominal, natomiast nie wiem czemu się tak dzieje. Zdefiniowałem odpowiedni konstruktor, który tworzy obiekt na podstawie vectora.

5

szablony trzeba definiowac w jednym pliku. Nie rozdziela sie szablonow na osobne pliki*

*jest na to trick, ale to po prostu includowanie w odpowiednim miejscu drugiego pliku tak ze kompilator mysli ze jest to jeden plik

0

Dzięki wielkie. A jakbym chciał zastosować ten trick to jak powinno wyglądać dokładnie to includowanie?

1

Ja dodam, że ludzie próbowali zmodyfikować kompilator, tak by można było definiować ciała funkcji szablonów cpp, licząc na poprawę wydajności konkretyzowania szablonu.
Zysk był pomijalnie mały więc stwierdzono, że nie ma sensu modyfikować kompilatora.
Cały problem wynika z tego, że szablon nabiera sensu w momencie użycia (konkretyzacji) a nie w momencie kompilacji wzorca szablonu.
Żeby móc skonkretyzować szablon, potrzebna jest pełna jego definicja, dlatego wszystko musi być w nagłówku.

1

W pliku Polynominal.cpp dodaj wymuszenie konkretyzacji szablonu jako...

template class Polynomial<double>;

Na końcu tego pliku. Osobiście w projektach takie wymuszenia wpisuję w włączanym poprzez #include pliku *.tcc.
Oto źródło rozwiewające mit że "używając szablonu kod implementacji koniecznie powinien być w pliku nagłówku": https://isocpp.org/wiki/faq/templates#separate-template-fn-defn-from-decl
https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file

1

Mit czy nie mit, umieszczenie wszystkiego w jednym pliku to najczęstszy sposób.

Jawna konkretyzacja w pliku .cpp jak najbardziej działa, ale wtedy ograniczamy się do tych wymienionych tam konkretyzacji i kiedy potrzeba nowej to trzeba dopisywać do listy...

C++ właściwie nie ma dobrego, eleganckiego rozwiązania tego problemu.

1 użytkowników online, w tym zalogowanych: 0, gości: 1