2011-01-31 15 views
8

Esta pregunta obviamente asume que no queremos usar plantillas para este tipo (por las razones que sean).¿C++ 0x permite decltype() en la firma de la función?

class Product 
{ 
public: 
    Product(decltype(mPrice) price_, decltype(mLabel) label_) // 1. 
     : mPrice(price_), mLabel(label_) 
    {} 

    decltype(mPrice) price() const {return mPrice;} // 2. 
    decltype(mLabel) label() const {return mLabel;} // 2. 


private: 

    float mPrice ; // type might later be changed to more acurate floating point abstraction 
    std::string mLabel; // type might later be changed by a special localization-oriented string 
}; 

La pregunta es: se 1. y 2. permitido y posible (o incluso específicamente definido) en C++ 0x?

Respuesta

7

Todo lo que tiene que hacer es declarar mPrice y mLabelantes utiliza decltype:

class Product 
{ 
private: 
    float mPrice ; 
    std::string mLabel; 
public: 
    Product(decltype(mPrice) price_, decltype(mLabel) label_) // 1. 
     : mPrice(price_), mLabel(label_) 
    {} 

    decltype(mPrice) price() const {return mPrice;} // 2. 
    decltype(mLabel) label() const {return mLabel;} // 2. 
}; 

Este compila bien bajo g ++ 4.4 con -std = C++ 0x.

Editar El punto es que el compilador tiene que ser capaz de analizar las declaraciones de funciones en la primera pasada. El cuerpo de una función miembro se puede compilar después de analizar las declaraciones de los miembros, pero las declaraciones de los miembros deben ser inmediatamente inteligibles; de lo contrario, ¿dónde comienza el compilador deficiente?

Por lo tanto, el tipo de cada argumento de función miembro debe conocerse tan pronto como se encuentre.

+0

¡Genial! ¿Es un comportamiento estándar o solo un comportamiento de implementación de gcc? – Klaim

+0

Hasta donde yo sé, este es el comportamiento estándar. – TonyK

+0

@Klaim El estándar dice "Un tipo de devolución tarde especificado es más útil para un tipo que sería más complicado de especificar antes del declarator-id" que parece indicar que poner el decltype antes de que la función sea válida y el valor de retorno final es opcional para casos donde es más fácil (o lamdas donde sea necesario) – MerickOWA

8

Sí, pero con una sintaxis diferente:

auto price() -> decltype(mPrice) { return mPrice; } 
auto price() -> decltype(mPrice) { return mPrice; } 

más general:

auto function(...) -> decltype(EXPRESSION) ... 

function tipo de retorno será el tipo de EXPRESSION


EDITAR

sobre el caso 1 No estoy seguro. No creo que sea válido, ya que no creo que mPrice sea una expresión válida en dicho contexto: está utilizando un miembro de función no estática (Product::mPrime) sin un objeto.

Supongo que si mPrime fuera un miembro estático, funcionaría.

+0

¿Estás seguro? Obtengo un error de compilación con g ++ porque las variables no están dentro del alcance (lo cual tiene sentido ya que son variables de instancia). – Motti

+0

No responde por el 1. caso. – Klaim

+0

@Klaim: actualizó mi respuesta – peoro

1

AFAIK esto es no legal ya que las variables de instancia no están en el alcance en los puntos que las usa.

Considere qué pasaría si tuviera las siguientes variables declaradas antes de su clase:

int mPrice; 
char mLabel; 
class Product 
{ /*...*/ }; 

En el decleration función mPrice uniría a la variable global más que el miembro de instancia.

Ambos g ++ 4.5 y VS10 se niegan a compilar su código ya que mPrice y mLabel están fuera del alcance.

Sin embargo, esto parece ser inconsistente con los parámetros predeterminados.

int mPrice = 3; 
class Product 
{ // ... 
    int foo(int i = mPrice) { return i; } 
}; 

Product p(5.3, "hi"); 
std::cout << p.foo(); 

Esto me da un error de compilación:

invalid use of non-static data member 'Product::mPrice'

+0

Bueno, no sé, porque decltype() acepta expresiones, por lo que el punto es que la expresión no se evalúa en este caso, pero está en tu ejemplo. Entonces, lo que estoy preguntando es en el caso de decltype(), ¿será capaz de usar la expresión o está explícitamente prohibido? – Klaim

2

VC++ 2010 compila este w/o errores:

 

class Product 
{ 
private: 

    float mPrice ; 
    std::string mLabel; 
public: 
    Product(decltype(mPrice) price_, decltype(mLabel) label_) 
     : mPrice(price_), mLabel(label_){} 

    auto price(decltype(mPrice)* p=NULL) const -> decltype(mPrice) {return mPrice;} 

    auto label(decltype(mPrice)* m=NULL) const -> decltype(mLabel) {return mLabel;} 

}; 

pero si quito los parámetros por defecto de los métodos ficticias declaraciones, vuelve a aparecer el error. decltype en return type funciona solo si también aparece en algún parámetro de función (???)

(Disculpe, entiendo que debería ser un comentario, pero parece interesante y no es conveniente poner código en los comentarios)

+0

Esto compila bien en g ++ 4.4.0 con -std = C++ 0x, incluso después de eliminar los parámetros predeterminados ficticios. Ver http://ideone.com/jGrak para prueba. – TonyK

+0

@TonyK: no tenía casi ninguna duda de que gcc debería compilar este código si compila el código que presenta en su respuesta. Los errores son probablemente específicos de msvC++, pero muy extraño, sin embargo. – user396672

+0

Curiosamente, no parece importar el parámetro, siempre que haya uno. El parámetro podría ser simplemente "precio automático (int = 0)" y aún funciona. – MerickOWA

Cuestiones relacionadas