Wywołanie funkcji szablonowej a wynik jej działania

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?

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
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ść.

4

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

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

Kompilator traktuje je wtedy jako obiekty typu std::string

8

Jak robisz:

funkcja("B", "A");

Kompilator dokona dedukcji argumentów do:

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:

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

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

using namespace std::string_literals;
// albo
using namespace std::literals;
using namespace std::literals::string_literals;
3
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.

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