2012-08-11 7 views
6

¿Es este C++ válido (teniendo en cuenta el último estándar)? Estoy obteniendo errores de compilación con casi-top-of-tree clang/libC++ en Ubuntu 12.04. Si es válido, enviaré la lista clang-dev con mensajes de error y cosas por el estilo.¿Es unordered_set <reference_wrapper <Ty>> válido?

#include <functional> 
#include <unordered_set> 

struct X 
{ 
    int i; 
}; 

void f() 
{ 
    std::unordered_set<std::reference_wrapper<X>> setOfReferencesToX; 

    // Do stuff with setOfReferencesToX 
} 

** Como nota aparte, estoy cansado de calificar que la pregunta/respuesta es específica del último estándar. ¿Podría la comunidad C++ en su conjunto, por favor empezar a calificar cosas que son específicas del antiguo estándar en su lugar? El estándar más nuevo ha estado fuera por alrededor de un año.

+1

+1 para la nota final. – Griwes

+0

"¿Podría la comunidad C++ en su conjunto, por favor, comenzar a calificar cosas que son específicas del antiguo estándar en su lugar?" No. Dado el gran número de usuarios que no pueden actualizarse a un compilador con compatibilidad más completa con C++ 11, y mucho menos con la popularidad de una cierta familia de compiladores que solo está actualizando lentamente su compatibilidad con C++ 11, C++ está funcionando para significar C++ 03 por lo menos otro año si no dos. Y no olvidemos que ni GCC ni Clang afirman una conformidad total con C++ 11. El futuro no es el presente, y pretender que es así no lo hará. –

Respuesta

8

El problema no es específico de std::reference_wrapper<T>, sino del tipo X.

El problema es que std::unordered_set requiere que defina funtores de hash e igualdad para std::reference_wrapper<X>. Puede pasar el funtor hash como segundo parámetro de plantilla.

Por ejemplo, esto funcionaría:

#include <functional> // for std::hash<int> 

struct HashX { 
    size_t operator()(const X& x) const { 
    return std::hash<int>()(x.i);  
    } 
}; 

y luego

std::unordered_set<std::reference_wrapper<X>, HashX> setOfReferencesToX; 

Otra opción es hacer una especialización para std::hash<X>:

namespace std { 
template <> 
struct hash<X> { 
    size_t operator()(const X& x) const { 
    return std::hash<int>()(x.i);  
    } 
}; 
} 

Esto le permite evitar de manera explícita especificando el segundo argumento de la plantilla:

std::unordered_set<std::reference_wrapper<X>> setOfReferencesToX; 

En cuanto a la comparación de igualdad, se puede solucionar este problema proporcionando un operador de igualdad para la clase X:

struct X 
{ 
    bool operator==(const X& rhs) const { return i == rhs.i; } 
    int i; 
}; 

De lo contrario, puede definir su propio funtor y pasarlo como argumento tercera plantilla.

+0

¿No se especializaría 'std :: hash' en ser un poco más simple? – Griwes

+0

Lo haría, si está dispuesto a poner cosas en el espacio de nombres 'std'. – juanchopanza

+0

No creo que deba ser calificado como "poner cosas en' std' ", ya que es una mera especialización ... – Griwes

Cuestiones relacionadas