2011-02-06 22 views
5

Tengo un std :: map de Poco :: Cualquier que estoy tratando de iterar y dar salida a una secuencia, pero estoy obteniendo un error de compilación. Mi código es el siguiente:No se puede iterar std :: map de Poco :: Any

map<string, Poco::Any>::const_iterator it; 
map<string, Poco::Any>::const_iterator end = _map.end(); 
map<string, Poco::Any>::const_iterator begin = _map.begin(); 
for(it = begin; it != end; ++it) { 
    const std::type_info &type = it->second.type(); 

    // compile error here: 
    os << " " << it->first << " : " << Poco::RefAnyCast<type>(it->second) << endl; 
} 

2 errores en esa línea:

'type' cannot appear in a constant-expression 
no matching function for call to 'RefAnyCast(Poco::Any&)' 

ACTUALIZACIÓN:

entiendo que las plantillas son tiempo de compilación mientras que el tipo() es el tiempo de ejecución por lo que no lo hará trabajo. Gracias por subrayar eso. Además, DynamicAny no funcionará porque solo acepta tipos que tienen implementaciones DynamicAnyHolder, no es ideal. La única regla que me gustaría imponer sobre los tipos es que tienen < < sobrecargado.

Debajo está lo que estoy haciendo actualmente, funciona hasta cierto punto, pero solo descarga tipos conocidos, que no es lo que estoy buscando.

string toJson() const { 
    ostringstream os; 
    os << endl << "{" << endl; 
    map<string, Poco::Any>::const_iterator end = _map.end(); 
    map<string, Poco::Any>::const_iterator begin = _map.begin(); 
    for(map<string, Poco::Any>::const_iterator it = begin; it != end; ++it) { 
     const std::type_info &type = it->second.type(); 
     os << " " << it->first << " : "; 

     // ugly, is there a better way? 
     if(type == typeid(int)) os << Poco::RefAnyCast<int>(it->second); 
     else if(type == typeid(float)) os << Poco::RefAnyCast<float>(it->second); 
     else if(type == typeid(char)) os << Poco::RefAnyCast<char>(it->second); 
     else if(type == typeid(string)) os << Poco::RefAnyCast<string>(it->second); 
     else if(type == typeid(ofPoint)) os << Poco::RefAnyCast<ofPoint>(it->second); 
     else if(type == typeid(ofVec2f)) os << Poco::RefAnyCast<ofVec2f>(it->second); 
     else if(type == typeid(ofVec3f)) os << Poco::RefAnyCast<ofVec3f>(it->second); 
     //else if(type == typeid(ofDictionary)) os << Poco::RefAnyCast<ofDictionary>(it->second); 
     else os << "unknown type"; 

     os << endl; 
    } 
    os<< "}" << endl; 
    return os.str(); 
} 

Respuesta

7

La información del tipo de tiempo de ejecución no se puede utilizar para crear instancias de plantillas. Una instancia de type_info cuyo valor solo se conocerá al ejecutar el programa, no se convierte mágicamente en un tipo como int, std::string o struct FooBar cuando el compilador está compilando este código.

No sé biblioteca Poco, pero tal vez usted podría utilizar su otro Cualquier tipo, DynamicAny (ver documentation), que se espera pueda permitirá convertir el valor almacenado a std::string para dar salida:

os << " " << it->first << " : " << it->second.convert<std::string>() << endl; 
+3

+1 . Quizás debería destacarse que las plantillas C++ son una tarea en tiempo de compilación y que los parámetros de la plantilla deben conocerse en tiempo de compilación. Al ver que el OP no podía entender qué estaba mal, esto podría ser una noticia para el OP. – sellibitze

+0

"Quizás debería destacarse que las plantillas C++ son una tarea en tiempo de compilación y que los parámetros de la plantilla deben conocerse en tiempo de compilación". Sí, esto lo aclara perfectamente gracias. Desafortunadamente, DynamicAny no admite realmente * Any * type, solo aquellos para los que existe una implementación DynamicAnyHolder, por lo que no admitirán tipos de usuario (por ejemplo, vectores, matrices, etc.) que tengan el operador << sobrecargado, pero Me gustaría evitar que todo extienda DynamicAnyHolderImpl si es posible. – memo

+0

@Memo: Desafortunadamente, solo la clase valueholding concreta (en boost 'holder ') bajo el cofre sabría cómo generar el valor retenido. Parece que tal vez no haya una manera de hacer que uno acepte visitas, por lo que la única opción podría ser agregarle un método que genere el valor, o al menos un método 'to_string'. http://codepad.org/NICm5r2r es simplemente 'boost :: any' modificado para tener un método' to_string' ('stringifier ' está ahí para agregar una posibilidad de costumización, pero la implementación predeterminada con 'boost :: lexical_cast' debería estar bien para todos los objetos "cout-able" excepto 'const char *'. – UncleBens