2010-08-28 22 views
19

Si usted tiene esta funcióndirecta perfecta en C++ 03

template<typename T> f(T&); 

Y luego tratar de llamarlo con, digamos un valor de lado derecho como

f(1); 

¿Por qué no se acaba de T se deduce ser const int, haciendo que el argumento sea const int & y por lo tanto enlazable a un valor de r?

Respuesta

18

Esto se menciona como una solución potencial en the document I vinculado en el recent C++0x forwarding question.

Es funcionan bastante bien, pero se rompe el código existente. Consideremos (directamente desde el documento):

template<class A1> void f(A1 & a1) 
{ 
    std::cout << 1 << std::endl; 
} 

void f(long const &) 
{ 
    std::cout << 2 << std::endl; 
} 

int main() 
{ 
    f(5);    // prints 2 under the current rules, 1 after the change 
    int const n(5); 
    f(n);    // 1 in both cases 
} 

O

// helper function in a header 

template<class T> void something(T & t) // #1 
{ 
    t.something(); 
} 

// source 

#include <vector> 

void something(bool) // #2 
{ 
} 

int main() 
{ 
    std::vector<bool> v(5); 

    // resolves to #2 under the current rules, #1 after the change 
    something(v[0]); 
} 

Esto también se abstiene de comunicar la categoría de valor (valor-I o rvalue), que no es un gran problema en C++ 03 . Pero dado que esta corrección solo se podía hacer durante C++ 0x, nos desconectaríamos efectivamente de las referencias rvalue al reenviar (algo malo). Deberíamos esforzarnos por una mejor solución.

1

Lo es, pero solo si declara f para tomar T const &.

template <typename T> void f(T &); 
template <typename T> void g(T const &); 

void x() { f(1); } // error: invalid initialization of non-const reference 
void y() { g(1); } // no error 

Y si se declara tantof(T &) y f(T const &), que va a elegir el const-cualificado uno:

template <typename T> void f(T &); 
template <typename T> void f(T const &); 

void x() { f(1); } // no error, calls f(T const &) 

Ahora tal vez usted está diciendo “ en el primer ejemplo, ¿por qué lo hace generar un temporal de tipo int para la llamada a f cuando podría haber generado un temporal de tipo const int e hizo el código compilar? ” La mejor respuesta que tengo para usted es que eso sería inconsistente con el comportamiento de resolución de sobrecarga cuando el argumento no es una constante entera.

+0

Sí, sé sobre la sobrecarga. Quería saber por qué es incluso necesario. ¿Cómo sería inconsistente? – Puppy

+0

@DeadMG: '1' tiene tipo' int'. Si declara un 'int i = 1', entonces elegiría el enfoque no const, porque' i' no es const. Por lo tanto, para mayor coherencia, aquí también lo hace, excepto que para un valor r es un error. –

+0

@ Matthieu: 1 es un valor int. yo soy un int lvalue Como el idioma insiste en tratarlos de manera diferente, entonces son cosas diferentes. Por lo tanto, no es inconsistente. De hecho, es incoherente tener un conjunto de reglas especialmente para los valores r, y luego tratar de tratarlos de la misma manera aquí. – Puppy

Cuestiones relacionadas