estoy usando un recipiente para contener una lista de punteros a cualquier cosa:Comparar impulsar :: cualquier contenido
struct Example {
std::vector<boost::any> elements;
}
Para insertar elementos en este contenedor, que había escrito un par de funciones de ayuda (miembros de la struct Example
):
void add_any(boost::any& a) {
elements.push_back(a);
}
template<typename T>
void add_to_list(T& a) {
boost::any bany = &a;
add_any(bany);
}
Ahora, me gustaría insertar elementos solo cuando no están presentes en este contenedor. Para hacer esto, pensé que solo necesitaría llamar al search
sobre elements
con una función de comparador apropiada. Sin embargo, no sé cómo comparar las instancias boost::any
.
Mi pregunta: Sabiendo que mis boost::any
casos siempre contienen un puntero a algo; ¿es posible comparar dos valores de boost::any
?
actualización
que gracias por sus respuestas. También he logrado hacer esto en un probablemente manera insegura: usando boost::unsafe_any_cast
para obtener un void**
y comparando el puntero subyacente.
Por el momento, esto está funcionando bien. Sin embargo, apreciaría sus comentarios: ¡quizás esto sea un gran error!
#include <boost/any.hpp>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
bool any_compare(const boost::any& a1, const boost::any& a2) {
cout << "compare " << *boost::unsafe_any_cast<void*>(&a1)
<< " with: " << *boost::unsafe_any_cast<void*>(&a2);
return (*boost::unsafe_any_cast<void*>(&a1)) ==
(*boost::unsafe_any_cast<void*>(&a2));
}
struct A {};
class Example {
public:
Example() : elements(0),
m_1(3.14),
m_2(42),
m_3("hello"),
m_4() {};
virtual ~Example() {};
void test_insert() {
add_to_list(m_1);
add_to_list(m_2);
add_to_list(m_3);
add_to_list(m_4);
add_to_list(m_1); // should not insert
add_to_list(m_2); // should not insert
add_to_list(m_3); // should not insert
add_to_list(m_4); // should not insert
};
template <typename T>
void add_to_list(T& a) {
boost::any bany = &a;
add_any(bany);
}
private:
vector<boost::any> elements;
double m_1;
int m_2;
string m_3;
A m_4;
void add_any(const boost::any& a) {
cout << "Trying to insert " << (*boost::unsafe_any_cast<void*>(&a)) << endl;
vector<boost::any>::const_iterator it;
for (it = elements.begin();
it != elements.end();
++it) {
if (any_compare(a,*it)) {
cout << " : not inserting, already in list" << endl;
return;
}
cout << endl;
}
cout << "Inserting " << (*boost::unsafe_any_cast<void*>(&a)) << endl;
elements.push_back(a);
};
};
int main(int argc, char *argv[]) {
Example ex;
ex.test_insert();
unsigned char c;
ex.add_to_list(c);
ex.add_to_list(c); // should not insert
return 0;
}
Nota al margen: Las funciones 'add_any' y' add_to_list' deberían tener una referencia constante como parámetro. Además, puede considerar usar un 'conjunto' en lugar de un' vector' si desea exclusividad. Aún necesitarías una función de comparación, por supuesto. –
Buena pregunta. Probablemente no sea posible. Sin embargo, si está dispuesto a implementar * su propio * any, hay una forma de hacerlo (con * run time fail * si los tipos subyacentes son los mismos, pero no son compatibles con la semántica de comparación) –
¿Está seguro de que ¿Desea almacenar la dirección del parámetro en el helper 'add_to_list'? Tenga en cuenta que 'boost :: any' copiará el objeto, pero en este caso el objeto es un puntero. –