2008-10-23 3 views
6

que estoy recibiendo un error extraño de g++ 3.3 en el siguiente código:dos o más tipos de datos de C++ en la declaración

#include <bitset> 
#include <string> 

using namespace std; 

template <int N, int M> 
bitset<N> slice_bitset(const bitset<M> &original, size_t start) { 
    string str = original.to_string<char, char_traits<char>, allocator<char> >(); 
    string newstr = str.substr(start, N); 
    return bitset<N>(newstr); 
} 

int main() { 
    bitset<128> test; 
    bitset<12> result = slice_bitset<12, 128>(test, 0); 
    return 0; 
} 

El error es el siguiente:

 
In function `std::bitset slice_bitset(const std::bitset&, unsigned int)': 
syntax error before `,' token 
`char_traits' specified as declarator-id 
two or more data types in declaration of `char_traits' 
`allocator' specified as declarator-id 
two or more data types in declaration of `allocator' 
syntax error before `>' token 

tiene que ser algo realmente tonto, pero ya se lo conté a mi pato de goma y a un amigo sin éxito.

Gracias, Lazyweb.

+2

+1 por decírselo a tu pato de goma. – Robert

Respuesta

10

La respuesta seleccionada de CAdaker anterior resuelve el problema, pero no explica por qué resuelve el problema.

Cuando se analiza una plantilla de función, la búsqueda no se realiza en tipos dependientes. Como resultado, las construcciones tales como los siguientes se pueden analizar:

template <typename T> 
class B; 

template <typename T> 
void foo (B<T> & b) { 
    // Use 'b' here, even though 'B' not defined 
} 

template <typename T> 
class B 
{ 
    // Define 'B' here. 
}; 

Sin embargo, esta "característica" tiene un coste, y en este caso es que la definición de 'foo' requiere consejos sobre el contenido de la plantilla 'B'. Si 'foo' utiliza un tipo anidado de 'B', entonces la palabra clave typename se requiere para decirle al compilador que el nombre es un tipo:

template <typename T> 
void foo (B<T> & b) 
{ 
    typename B<T>::X t1; // 'X' is a type - this declares t1 
    B<T>::Y * t1;   // 'Y' is an object - this is multiplication 
} 

Sin 'nombretipo' en lo anterior, el compilador asumirá que X es un objeto (o función).

Del mismo modo, si una función miembro se ha llamado y la llamada tiene argumentos de plantilla explícitas a continuación, el compilador necesita saber para tratar la < como el inicio de una lista de argumentos plantilla y no el operador menos de:

template <typename T> 
void foo (B<T> & b) 
{ 
    b.template bar<int> (0); // 'bar' is a template, '<' is start of arg list 
    b.Y < 10;    // 'Y' is an object, '<' is less than operator 
} 

Sin template, el compilador supone que < es el menor que el operador, por lo que genera el error de sintaxis cuando ve int> ya que no es una expresión.

Estas sugerencias son necesarias incluso cuando la definición de la plantilla es visible. La razón es que una especialización explícita podría cambiar posteriormente la definición que realmente se eligió:

template <typename T> 
class B 
{ 
    template <typename S> 
    void a(); 
}; 

template <typename T> 
void foo (B<T> & b) 
{ 
    b.a < 10;   // 'B<int>::a' is a member object 
} 

template <> 
class B<int> 
{ 
    int a; 
}; 
7

uso ya sea solo

original.to_string(); 

o, si realmente necesita los especificadores de tipo,

original.template to_string<char, char_traits<char>, allocator<char> >(); 
+0

En este caso, to_string no tiene especificación predeterminada, ¡pero su última respuesta funciona! Gracias. – cdleary

2

Los siguientes compilado para mí (con gcc 3.4.4):

#include <bitset> 
#include <string> 

using namespace std; 

template <int N, int M> 
bitset<N> slice_bitset(const bitset<M> &original, size_t start) 
{ 
    string str = original.to_string(); 
    string newstr = str.substr(start, N);  
    return bitset<N>(newstr); 
} 

int main() 
{ 
    return 0; 
} 
+0

Sí, pero no se compilará si realmente llama a la función y evalúa los parámetros de la plantilla. – cdleary

+0

Añadiendo #include y cambiando main a esto compilado (con gcc 4.0.1): int main() { bitset <4> orig; orig.set (0,0); orig.set (1,1); orig.set (2,0); orig.set (3,1); conjunto de bits <2> bits = slice_bitset <2,4> (orig, 2); cout << bits.to_string() << endl; return 0; } ¿Qué error estás recibiendo? –

+0

Recibo el mismo error que el anterior. Estoy usando g ++ 3.3, sin embargo, pueden haber actualizado el stdlib en g ++ para incluir un parámetro de plantilla predeterminado en 3.4, pero cplusplus.com dice "no están deducidos implícitamente por el compilador". (http://www.cplusplus.com/reference/stl/bitset/to_string.html) – cdleary

Cuestiones relacionadas