Domanda

Ricevo uno strano errore da g++ 3.3 nel seguente codice:

#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;
}

L'errore è il seguente:

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

Deve essere qualcosa di veramente stupido, ma l'ho già detto alla mia papera di gomma e ad un amico senza risultati.

Grazie, Lazyweb.

È stato utile?

Soluzione

La risposta selezionata da CAdaker sopra risolve il problema, ma non spiega perché risolve il problema.

Quando viene analizzato un modello di funzione, la ricerca non avviene in tipi dipendenti. Di conseguenza, è possibile analizzare costrutti come i seguenti:

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.
};

Tuttavia, questa " caratteristica " ha un costo e, in questo caso, la definizione di "pippo" richiede suggerimenti sul contenuto del modello "B". Se "pippo" utilizza un tipo nidificato di "B", la parola chiave typename è obbligatoria per indicare al compilatore che il nome è 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
}

Senza "typename" sopra, il compilatore supporrà che X sia un oggetto (o una funzione).

Allo stesso modo, se viene chiamata una funzione membro e la chiamata ha argomenti modello espliciti, il compilatore deve sapere di trattare < come l'inizio di un elenco di argomenti modello e non meno di operatore:

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
}

Senza template, il compilatore presuppone che int> sia l'operatore minore di e quindi genera l'errore di sintassi quando vede <=> poiché non si tratta di un'espressione.

Questi suggerimenti sono richiesti pari quando la definizione del modello è visibile. Il motivo è che una specializzazione esplicita potrebbe successivamente modificare la definizione effettivamente scelta:

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;
};

Altri suggerimenti

Usa solo

original.to_string();

oppure, se hai davvero bisogno degli identificatori di tipo,

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

Il seguente è stato compilato per me (usando 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; 
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top