byłem ciekaw dlaczego ten fragment kodu nie działa:namespace std przeciążenia mniej niż
#include "stdafx.h"
#include <iostream>
#include <tuple>
#include <string>
#include <vector>
#include <algorithm>
typedef std::tuple<int, std::string> intString;
bool operator<(intString& lhs, intString& rhs){
return std::tie(std::get<1>(lhs), std::get<0>(lhs)) < std::tie(std::get<1>(rhs), std::get<0>(rhs));
}
void printIntStrings(std::vector<intString>& v){
for (intString& i : v){
std::cout << std::get<0>(i) << " is " << std::get<1>(i) << std::endl;
}
}
int main(int argc, char* argv[])
{
std::vector<intString> v;
v.push_back(std::make_tuple(5, "five"));
v.push_back(std::make_tuple(2, "two"));
v.push_back(std::make_tuple(9, "nine"));
printIntStrings(v);
std::sort(v.begin(), v.end());
printIntStrings(v);
return 0;
}
O ile mogę zrozumieć, po prostu stworzyć wektor intStrings i mój operator powinien sortować według drugi element w krotce pierwszy więc wyjście powinno być (ostatnie 3 linie tak)
5 five
9 nine
2 two
jednak działa to na moim komputerze mam
2 two
5 five
9 nine
co oznacza, że sortowanie używa wartości domyślnej mniejszej niż operator, ignorując podaną przeze mnie. Zauważ, dodając const, zanim parametry nie wpłynęły na nic.
Znalazłem trzy sposoby "naprawienia" tego.
Fix # 1
bool operator przestrzenny < ... w przestrzeni nazw std tak:
namespace std{
bool operator<(intString& lhs, intString& rhs){
return std::tie(std::get<1>(lhs), std::get<0>(lhs)) < std::tie(std::get<1>(rhs), std::get<0>(rhs));
}
}
Jednak powiedziano mi, że nigdy nie powinno się dodać rzeczy do przestrzeni nazw std ponieważ zachowanie jest undefined, więc ta poprawka wydaje się najgorsza.
Fix # 2
Dodaj coś zwyczaj krotki tak:
enum class TRASH{DOESNTMATTER};
typedef std::tuple<int, std::string, TRASH> intString;
bool operator<(intString& lhs, intString& rhs){
return std::tie(std::get<1>(lhs), std::get<0>(lhs)) < std::tie(std::get<1>(rhs), std::get<0>(rhs));
}
(i oczywiście dodać w Koszu :: DOESNTMATTER jako trzeci argument make_tuple) Jednak wydawało jak dużo pracy za coś tak prostego. Wydaje się też, że marnotrawstwo nie jest sensownie używane.
Fix # 3
Użyj rodzaju źródłowe tak:
std::sort(v.begin(), v.end(), operator<);
To wydawało się być najbardziej eleganckie rozwiązanie. Jednak nie widzę powodu, dla którego muszę wyraźnie powiedzieć kompilator, aby użyć mojego zdefiniowanego operatora <.
Więc chcę wiedzieć:
1) dlaczego tak się dzieje? Nie powinienem C++ znaleźć mojej implementacji i użyć tego?
2) które "naprawić" jest najlepsze? jeśli żaden z tych, które znalazłem, co poleciłbyś?
Wszelkie pomysły? Dziękuje za przeczytanie!
Standardowy operator '' jest lepiej dopasowany, ponieważ jego parametry to 'const'. – Oktalist
@Oktalist Ups, zapomniałem wspomnieć o dodaniu stałej, zanim oba parametry nie pomogły. edytuje –
Problem polega na tym, że istnieje'already_ 'operator <' dla krotek, więc kompilator używa oficjalnego zamiast hackera. –