2009-11-05 3 views
0
#include <iostream> 
#include <vector> 
#include <algorithm> 
#include <iterator> 
#include <functional> 
#include <deque> 
using namespace std; 

#include <tr1/functional> 
using namespace std::tr1::placeholders; 
template<class Function_t> 
void for_each_x(Function_t func,int interval) 
{ 
    for(int sc = 0; sc < 10; sc+=interval){ 
     func((const int)sc); 
    } 
} 
void foo(int x,const int y) 
{ 
} 

int main(int argc, char *argv[]) 
{ 
    for_each_x(tr1::bind(tr1::function<void(int,const int)>(foo),_1,11),2); 
    return 0; 
} 

gcc 4.2.2 ou 4.4.1 donne très long message d'erreur. si je change le "const int" à "int", alors pas de message d'erreur. Mais j'aime vraiment avoir le "const int" pour m'assurer que la variable du compteur ne change pas par accident si l'argument de la fonction est passé par référence.pourquoi TR1 :: bind ne peut pas être compilé si le type d'argument est "const int"

Répondre

3

Une expression est non seulement classée par son type, mais également par son caractère lgrant. Celui-ci détermine principalement s'il est stocké quelque part, et il détermine également s'il peut être lié à des références non-const. Une rvalue non-const (non-lvalue) ne peut pas être lié à des références non-const, donc si vous faites ce qui suit, vous ne parvenez pas toujours:

template<typename T> 
void f(T&); 
int main() { f(10); f((int const)10); } 

Le deuxième appel peut vous surprendre, mais en fait qualificatifs cv-sont abandonné des valeurs de non-classe, et donc l'expression de cast arrive à avoir le type int, toujours. Ainsi, le type de paramètre du modèle de fonction sera déduit à int& - la compilation échoue. Maintenant, pré-C++ 0x bind supporte seulement les références non-const comme le type d'argument qu'il avance, donc si vous lui donnez un argument const, c'est bien - son paramètre template le fera devenir un const référence. Mais si vous lui donnez un argument non-const, et que c'est un rvalue, c'est pas bien, car il ne pourra pas être lié par le paramètre de référence.

Vous souhaitez appeler l'objet de liaison avec une valeur lvalue, c'est-à-dire avec sc ou avec une valeur lvalue constante. Notez également que les qualificatifs de niveau supérieur des types de paramètres de fonction sont supprimés, et donc foo a effectivement le type void(int, int) - ce cv-drop toplevel se produit pour tous les types de paramètres. Quoi qu'il en soit, la solution est de changer l'appel à

for(int sc = 0; sc < 10; sc+=interval){ 
    func((int const&)sc); // notice & 
} 
Questions connexes