Bonjour à tous (ça fait un bail que je passais plus par ici )

Voici un petit code sympa de foncteur générique simple.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template<class C, typename T, T C::*P>
struct by_member
{
	bool operator()(C const & rl, C const & rr) const
	{
		return rl.*P < rr.*P;
	}
	bool operator()(C const & rl, T const & t) const
	{
		return rl.*P < t;
	}
	bool operator()(T const & t, C const & rr) const
	{
		return t < rr.*P;
	}
};
Et voici un petit code exemple d'utilisation (je vous laisse ajouter les #include nécessaires si vous l'essayer).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
struct employee
{
	int         f_id;
	std::string f_firstname;
	std::string f_lastname;
	int         f_ssnumber;
 
	employee(int id, std::string const & firstname, std::string const & lastname, int ssnumber) :
		f_id(id), f_firstname(firstname), f_lastname(lastname), f_ssnumber(ssnumber) {}
};
 
typedef by_member<employee, std::string, &employee::f_lastname> by_lastname;
 
int _tmain(int argc, _TCHAR* argv[])
{
	std::vector<employee> v;
	v.push_back(employee(5, "John", "Smith", 1582));
	v.push_back(employee(3, "Paul", "Howard", 1777));
	v.push_back(employee(7, "Jude", "Muller", 1325));
	std::sort(v.begin(), v.end(), by_lastname());
	if ( std::binary_search(v.begin(), v.end(), "Muller", by_lastname()) )
		std::cout << "Found" << std::endl;
	return 0;
}
Simple, propre et efficace me semble-t-il.


Maintenant je souhaiterais un foncteur utilisant deux membres de employee (ou plus) afin de former une clé multiple permettant de trier puis rechercher sur, par exemple, f_lastname et f_firstname.

Je pensais adapter by_member<> comme ceci (c'est juste un début de réflexion):
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template<class C, typename T1, T1 C::*P1, typename T2, T2 C::*P2>
struct by_2_members
{
	bool operator()(C const & rl, C const & rr) const
	{
		return rl.*P1 < rr.*P1 || (rl.*P1 == rr.*P1 && rl.*P2 < rr.*P2);
	}
	bool operator()(C const & rl, Tuple? const & t) const
	{ // ici ça coince...
		return rl.*P1 < t<1> || (rl.*P1 == t<1> && rl.*P2 < t<2>);
	}
	bool operator()(Tuple? const & t, C const & rr) const
	{ // et ici aussi...
		return t<1> < rr.*P1 || (t<1> == rr.*P1 && t<2> < rr.*P2);
	}
};
Pour un usage comme ceci par exemple:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
typedef by_2_members<employee, std::string, &employee::f_lastname, std::string, &employee::f_firstname> by_lastname_firstname;
 
	...
 
	std::sort(v.begin(), v.end(), by_lastname_firstname());
	if ( std::binary_search(v.begin(), v.end(), std::tuple("Muller", "Jude"), by_lastname_firstname()) )
		std::cout << "Found" << std::endl;
Je n'aime que moyennement utiliser std::tuple<>, toute idée pour l'éviter est bienvenue.

Ensuite l'usage d'un variadic template pour écrire une forme générale de by_member<> serait pas mal aussi (sans tout transformer en usine à gaz).

Merci pour vos avis