2010-09-19 16 views
9
template<typename T1, typename T2> 
class Bimap { 
public: 
    class Data { 
    private: 
     template<typename T> Data& set(T); 
     template<> Data& set<T1>(typename T1 v) { /*...*/ } 
    }; 
}; 

Eso me da el error:C++: Error de "especialización explícita en el ámbito no-espacio de nombres"

error: explicit specialization in non-namespace scope 'class Bimap<T1, T2>::Data'

entiendo lo que está diciendo el error. ¿Pero por qué no puedo hacer esto? ¿Y cómo puedo solucionarlo?

+2

Merece la pena señalar que algunos compiladores soportarán esto. – Puppy

+1

En C++ no se puede especializar explícitamente una plantilla de miembro sin especializar explícitamente la plantilla de clase adjunta. Lo que estás intentando (es decir, la especialización) es * no posible *. Tienes que usar la sobrecarga. O rediseña todo por completo. MSVC++ es un compilador que permite esto como una extensión. – AnT

Respuesta

14

Una forma de olvidar las plantillas, sobrecarga:

Data& set(T1 v) { /*...*/ } 

pero aquí es un truco que utilizo a veces

puede especializarse plantilla de clase dentro de la clase:

class { 
    template<typename T> 
    struct function_ { 
     static void apply(T); 
    }; 

    template<> 
    struct function_<int> { 
     ... 
    }; 

    template<typename T> 
    void function(T t) { return function_<T>::apply(t); } 
+0

+1, sí, la única forma sensata de obtener especializaciones de plantillas de funciones correctas. –

+4

* Puedes * explícitamente especializar una plantilla de clase anidada dentro de una clase * ordinaria *. Pero usted * no puede * explícitamente especializar una plantilla de clase anidada dentro de otra * plantilla de clase *. La única forma de hacer esto último es explícitamente especializar * ambos * la plantilla adjunta y la plantilla anidada. – AnT

+0

@Andrey No estaba seguro acerca de la clase de plantilla dentro de la clase de plantilla. de todos modos, es probable que se pueda realizar alguna variación del truco – Anycorn

0

@Albert

Tuve un problema similar cuando quería agregar una "capacidad de recorte de exceso" a una personalizada hecho contenedor. El truco de intercambio de std :: vector y el cambio de la declaración del contenedor existente no eran opciones válidas. Así que he llegado con esto:

template <class T, bool isPtr> struct DeleteImp 
{ 
    static void Trim(T* to, unsigned int count); 
}; 

template <class T> struct DeleteImp<T, false>  
{ 
    static void Trim(T* to, unsigned int count) {} 
}; 

template <class T> struct DeleteImp<T, true>   
{ 
    static void Trim(T* to, unsigned int count) 
    { 
     for(unsigned int i=0; i<count; i++) 
      delete to[i]; 
    } 
}; 

utilizado por mi contenedor de esta manera:

DeleteImp<T, TypeTraits<T>::isPointer>::Trim(buf + length, truelength-length); 

También es posible que desee comprobar hacia fuera este resource.

Cuestiones relacionadas