(Nota: tuple
y tie
se puede tomar de Boost o C ++ 11.)
Cuando escribo estructuras pequeñas con solo dos elementos, a veces tiendo a elegir a std::pair
, ya que todas las cosas importantes ya están hechas para ese tipo de datos, como operator<
para el orden estricto-débil .
Sin embargo, las desventajas son los nombres de variables prácticamente inútiles. Incluso si yo mismo creé eso typedef
, no recordaré 2 días después qué first
y qué second
fue exactamente, especialmente si ambos son del mismo tipo. Esto se vuelve aún peor para más de dos miembros, ya que anidar pair
s apesta.
La otra opción para eso es untuple
, ya sea de Boost o C ++ 11, pero eso en realidad no se ve más agradable y claro. Así que vuelvo a escribir las estructuras yo mismo, incluidos los operadores de comparación necesarios.
Dado que especialmente operator<
puede ser bastante engorroso, pensé en eludir todo este lío simplemente confiando en las operaciones definidas para tuple
:
Ejemplo de operator<
, por ejemplo, para el orden estricto-débil:
bool operator<(MyStruct const& lhs, MyStruct const& rhs){
return std::tie(lhs.one_member, lhs.another, lhs.yet_more) <
std::tie(rhs.one_member, rhs.another, rhs.yet_more);
}
( tie
Hace que una tuple
de T&
las referencias de los argumentos pasados.)
Editar : La sugerencia de @DeadMG de heredar de tuple
forma privada no es mala, pero tiene algunos inconvenientes:
- Si los operadores son independientes (posiblemente amigos), necesito heredar públicamente
- Con el casting, mis funciones / operadores (
operator=
específicamente) se pueden omitir fácilmente - Con la
tie
solución, puedo dejar fuera a ciertos miembros si no son importantes para el pedido.
¿Hay algún inconveniente en esta implementación que deba considerar?
tie
no se puede aplicar a miembros de campo de bits.tie(...)
llamadas se van a duplicar en varios operadores (=, ==, <, etc.), puede escribir un método en línea privadomake_tuple(...)
para encapsularlo y luego llamarlo desde los otros lugares, como enreturn lhs.make_tuple() < rhs.make_tuple();
(aunque el tipo de retorno de ¡Ese método podría ser divertido de declarar!)auto tied() const{ return std::tie(the, members, here); }
Respuestas:
Sin duda, esto hará que sea más fácil escribir un operador correcto que hacerlo tú mismo. Yo diría que solo considere un enfoque diferente si la creación de perfiles muestra que la operación de comparación es una parte de su aplicación que requiere mucho tiempo. De lo contrario, la facilidad de mantenimiento debería superar cualquier posible problema de rendimiento.
fuente
tuple<>
eloperator<
que sea más lento que uno escrito a mano.Me he encontrado con este mismo problema y mi solución usa plantillas variadic de c ++ 11. Aquí viene el código:
La parte .h:
Y el .cpp para el caso base sin argumentos:
Ahora tu ejemplo se convierte en:
fuente
En mi opinión, todavía no está abordando el mismo problema que
std::tuple
resuelve, es decir, debe saber cuántos y el nombre de cada variable miembro, lo está duplicando dos veces en la función. Podrías optar por laprivate
herencia.Este enfoque es un poco más complicado para empezar, pero solo mantiene las variables y los nombres en un lugar, en lugar de en cada lugar para cada operador que desea sobrecargar.
fuente
T& one_member(){ return std::get<0>(*this); }
etc.? Pero, ¿no sería necesario que proporcione un método de este tipo para cada "miembro" que tengo, incluidas las sobrecargas para la versión const y no const?Si planea usar más de una sobrecarga de operador, o más métodos de tuple, le recomiendo hacer que tuple sea un miembro de la clase o derivar de tuple. De lo contrario, lo que estás haciendo es mucho más trabajo. Al decidir entre los dos, una pregunta importante a responder es: ¿Quieres que tu clase sea una tupla? Si no, recomendaría contener una tupla y limitar la interfaz mediante la delegación.
Puede crear descriptores de acceso para "cambiar el nombre" de los miembros de la tupla.
fuente
operator<
usando lostd::tie
razonable? " No entiendo cómo esta respuesta se relaciona con esa pregunta.