[C++/BCB/Turbo C++]Operacja modulo w szablonie

0

Mam dziwny błąd. Napisałem taką funkcję szablonową:

//definicja
template <class T>
T OperacjaArytmetyczna(T zm1, T zm2, AnsiString znak);
//opis
template <class T>
T TDrzewo::OperacjaArytmetyczna(T zm1, T zm2, AnsiString znak){
	if(znak=="+"){
		return zm1+zm2;
	}
	else if(znak=="-"){
		return zm1-zm2;
	}
	else if(znak=="*"){
		return zm1*zm2;
	}
	else if(znak=="/"){
		return zm1/zm2;
	}
	else{ //%
		return zm1%zm2;
	}
}

I przy kompilacji dostaje błąd:

[C++ Error] main.cpp(182): E2060 Illegal use of floating point w linii return zm1%zm2;

A przecież to funkcja szablonowa, która może mieć dowolny typ. Jeśli więc wstawię typ int, będzie wszystko ok. Skąd więc taki błąd, skoro kompilator nie ma pojęcia o typie zmiennych zm1 i zm2?</cpp>

0

A przecież to funkcja szablonowa, która może mieć dowolny typ

Nie jest to prawdą .
Kompilator tworzy fun . na podstawie szablonu , jeśli podasz typ zmiennej który
powoduje wygenerowanie nieprawidłowego kodu zgłosi błąd .

Używanie szablonów nie zwalnia programisty od wiedzy na temat w jaki sposób
funkcja działa ( zostanie wygenerowana na jego podstawie) w stosunku do typu przekazanej zmiennej ,,,

W takim przypadku należy napisać specjalizację dla danego typu .
Szablony nie są uniwersalne i pewne rozwiązania dotyczące przekazywanych typów
trzeba oprogramować oddzielnie lub w przypadku klas zapewnić odpowiednią konwersję typów .
Ps.

np. operator '%' nie może być używany w stosunku do zmiennej typu float .

//q: dokladnie.. nie wysypuje sie template sam z siebie, tylko jego konkretna, jedna specjalizacja, gdzie delikwent probuje podac float albo double za parametr <T>..

0

Dokładnie.
Rozwiązanie jest takie:

template <class T>
T modulo(T zm1, T zm2)
{
     return zm1%zm2;
}

// specjalizacja:
double modulo(double zm1, double zm2)
{
     return div(zm1,zm2).rem; // funkcja z stdlib
}
template <class T>
T OperacjaArytmetyczna(T zm1, T zm2, AnsiString znak);
//opis
template <class T>
T TDrzewo::OperacjaArytmetyczna(T zm1, T zm2, AnsiString znak){
        if(znak=="+"){
                return zm1+zm2;
        }
        else if(znak=="-"){
                return zm1-zm2;
        }
        else if(znak=="*"){
                return zm1*zm2;
        }
        else if(znak=="/"){
                return zm1/zm2;
        }
        else{ //%
                modulo(zm1,zm2); // tu stosuje szablon pomocniczy i specjalizację
        }
}
0

Mała poprawka :-P :

// specjalizacja:
double modulo(double zm1, double zm2)
{
     return modf (zm1,zm2); // funkcja z cmath
}
0

Coś mi tu nie gra :-P Funkcja modf z cmath zwraca cześć ułamkową to raz, a dwa że przecież tak na prawdę działa na jednym argumencie, bo drugi to wskaźnik pod którego adresem znajdzie się część całkowita liczby. Więc takie wywołanie:

return modf(liczba1,liczba2)

raczej nie przejdzie co nie?
Abstrahując już zupełnie od tego czy ma to cokolwiek wspólnego z operacją modulo [green]
http://www.cplusplus.com/reference/clibrary/cmath/modf.html
Moja propozycja:

return modf(liczba1/liczba2, &zmienna_na_czesc_calkowita)
0

Fakt nie doczytałem dokumentacji, ale wiadomo na czym polega filozofia z szablonem.

A jeśli już poprawiać to modulo to tak:

double modulo(double zm1, double zm2)
{
     return zm2*modf (zm1/zm2,&zm1); // funkcja z cmath
}

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