Domanda

Come parte di un compito a casa, siamo tenuti a mappare la presenza di ogni personaggio in una mappa. La nostra funzione si suppone di utilizzare std :: for_each e passare il carattere da valutare.

La mia funzione è:

std::for_each(document_.begin(), 
              document_.end(), 
              std::mem_fun(&CharStatistics::fillMap));

document_ è un string, e la funzione fillMap è definita come

void CharStatistics::fillMap(char ch)
{
    ch = tolower(ch);
    ++chars_.find(ch)->second;
}

chars_ è dichiarato come std::map<char, unsigned int> chars_;.

Immagino che questo dovrebbe funzionare, ma il compilatore si lamenta

error C2064: term does not evaluate to a function taking 1 arguments

Il che mi confonde, perché quando guardo la lista degli argomenti

_Fn1=std::mem_fun1_t<void,CharStatistics,char>,
1>            _Elem=char,
1>            _Traits=std::char_traits<char>,
1>            _Alloc=std::allocator<char>,
1>            _Result=void,
1>            _Ty=CharStatistics,
1>            _Arg=char,
1>            _InIt=std::_String_iterator<char,std::char_traits<char>,std::allocator<char>>

si guarda bene a me. _Elem è un char e la mia funzione accetta un char. L'iteratore non è altro che un char *

Che cosa sto facendo di sbagliato?

È stato utile?

Soluzione

CharStatistics::fillMap non è una funzione di prendere 1 argomento. di essa la funzione membro e quindi ha implicitamente primo argomento -. puntatore a un'istanza di classe

nel codice:

std::for_each(document_.begin(), 
              document_.end(), 
              std::mem_fun(&CharStatistics::fillMap));

for_each non so su quale istanza si desidera chiamare CharStatistics::fillMap, non è stato specificato di esso. hai bisogno di impegnare con qualsiasi istanza CharStatistics, per esempio:.

std::bind1st(std::mem_fun(&CharStatistics::fillMap), &char_statistics_instance)

Altri suggerimenti

document_ è una collezione di personaggi?

Ma la funzione è una funzione membro di CharStatistics! Presumibilmente si sta chiamando questo da una funzione di membro di CharStatistics. In questo caso è possibile usare boost :: bind di risolverlo se ciò è consentito:

std::for_each( document_.begin(), document_.end(), 
     boost::bind( &CharStatistics::fillMap, this, _1 );

Si potrebbe usare std :: bind1st su "questo" che è più complessa in quanto è comunque necessario mem_fun

std::for_each( document_.begin(), document_.end(), 
      std::bind1st( std::mem_fun(&CharStatistics::fillMap), this ) );

che in realtà è terribilmente complessa ricerca. Ecco perché il nuovo bind è molto meglio!

Se non si è autorizzati a utilizzare boost :: bind e non vi piace la soluzione mem_fun, scrivere il proprio funtore che sovraccarichi operatore () per prendere un char. In questo modo:

struct CharStatsFunctor
{
   typedef std::map< char, size_t > map_type;
   map_type & mapToFill;
   explicit CharStatsFunctor( map_type & m ) : mapToFill( m ) {}

   void operator()(char ch ) const
   {
       ++mapToFill[ ::tolower( ch ) ];
   }
};

Nella chiamata ciclo

std::for_each( document_.begin(), document_.end(), CharStatsFunctor( chars_ ) );

Nota c'è un errore nella funzione fillMap. La soluzione che ho dato funzionerà.

Fondamentalmente ciò che è sbagliato è che il contenitore ha un tipo di valore char, e for_each prevede una funzione che prende un argomento di char, ma valuta std::mem_fun(&CharStatistics::fillMap) ad un oggetto funzione che accetta un'istanza di CharStatistics (sul quale verrà poi chiama fillMap )

Perché non cambiare semplicemente la vostra funzione:

void CharStatistics::fillMap(std::string const& str)
{
  std::string::const_iterator it(str.begin()), end(str.end());
  for(; it != end; ++it)
    ++chars_.find(tolower(*it))->second;
}

Se CharStatistics::fillMap non è una funzione di membro static, allora avete bisogno di impegnare la chiamata a un'istanza:

CharStatistics instance;
std::for_each(
     document_.begin(),
     document_.end(),
     std::bind1st(
         &CharStatistics::fillMap,
         &instance
     )
);

Inoltre, se non è una funzione membro statica, quindi in realtà ha due argomenti. Il primo è il puntatore this implicita, e il secondo è il char. Quindi devi legare due argomenti, utilizzando boost::bind (o std::bind se si è in C ++ 0x):

CharStatistics instance;
std::for_each(
     document_.begin(),
     document_.end(),
     boost::bind(
         &CharStatistics::fillMap,
         &instance,
         _1
     )
);

for_each dovrebbe ora vedere l'istanza bind2nd come oggetto funzione prendendo un argomento (_1), e l'istanza verrà passata automaticamente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top