Wywołanie funkcji szablonowej a wynik jej działania

Wywołanie funkcji szablonowej a wynik jej działania
H5
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 66
0

Cześć,
mam najprostszą funkcję wykorzystującą szablony, która przyjmuje dwa argumenty tego samego rodzaju i zwraca większą wartość.
Jeżeli chodzi o liczby typu int czy double, działa poprawnie, natomiast problem pojawia się ze stringiem / charem.

Jeżeli wywołam funkcję w ten sposób:

funkcja<string>("A", "B");
lub
funkcja<char>('A', 'B');

Działanie programu także jest poprawne (czyli zwracane jest B, jako "większe"). Natomiast jeśli pozwolę na dedukcję typu, czyli wywołam funkcję w ten sposób:

funkcja("A", "B");

to wtedy funkcja zawsze zwraca pierwszy argument, to znaczy zawsze uznaje, że pierwszy jest większy. Jeżeli wywołam

funkcja("A", "B");

to zwróci A, a jeżeli zrobię to w ten sposób:

funkcja("B", "A");

to zwróci B.

Gdy pozwolę na dedukcję typów, to zmienne są typu const char*. Skąd wynika ten problem?

AK
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 3561
1

funkcja(const char * a, const char * b)

Mniemam, że UOGÓLNIONE porównanie masz operatorem <, <= itd
if(a<b)

Porównujesz wtedy fizyczną kolejność pointerów, a nie napisów na które wskazują. Elementarz C.

UPDATE
W ogóle tu z kilku stron kopie prymitywizm (kompatybilność w dół) C/C++.

  • w korpo-Javie byś musiał do typu mieć Comparator/Comparable a nie operator, kompilator by się nie pomylił
  • sam napis w Javie / C# nie jest typu prymitywnego przyległego obszaru znaczków w pamięci, a typem String / string
AL
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1493
3

"tekst" będzie mieć typ const char* czyli będzie c-stringiem, bo tak założyli twórcy języka; efekt tego taki, że będziesz porównywać wskaźniki, chyba że odpowiednio wyspecjalizujesz template'a. Ot, zaszłość.

TomaszLiMoon
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 530
4

Chyba najprostszym sposobem obejścia tego problemu jest użycie literałów z końcówką s.

Kopiuj
funkcja("B"s, "A"s);

Kompilator traktuje je wtedy jako obiekty typu std::string

MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
8

Jak robisz:

Kopiuj
funkcja("B", "A");

Kompilator dokona dedukcji argumentów do:

Kopiuj
funkcja<const char *>("B", "A");

a jako, że w kodzie zapewne masz porównanie, to porównywanie wskaźników nie daje ci tego co oczekujesz.

Najprostsze rozwiązanie to dopisać jawne przeciążenia tej funkcji (bez szablonów), wtedy będą one miały priorytet nad szablonem:

Kopiuj
bool funkcja(const char *, const char *);
bool funkcja(const wchar_t *, const wchar_t *);

Żeby to co @TomaszLiMoon zadziałało potrzebujesz:

Kopiuj
using namespace std::string_literals;
// albo
using namespace std::literals;
using namespace std::literals::string_literals;
_13th_Dragon
  • Rejestracja: dni
  • Ostatnio: dni
3
Kopiuj
template<typename T> int funkcja(T a,T b) { return a<b; }
template<> int funkcja(const char *a,const char *b) { return funkcja(string(a),string(b)); }

int main()
{
	//vector<RecordData> table;
	cout<<funkcja(1,2)<<endl;
	cout<<funkcja(2,1)<<endl;
	cout<<funkcja("a","b")<<endl;
	cout<<funkcja("b","a")<<endl;
	return 0;
}

Wystarczy wyróżnienie const char* reszta musi przejść wg standardowego wzorca.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.