2012-02-17 28 views
6

que tengo:decltype (función) como miembro de la clase

int foo(int x) { return x+1; } 

struct Bar { 
    decltype(foo) operator(); 
}; 

int main() { 
    Bar bar; 
    printf("%d\n",bar(6)); 
} 

que resulta en el mensaje de error compilador ligeramente sorprendente (g ++ 4.6.1):

error: declaration of 'operator()' as non-function 

Al cambiar el nombre del miembro a

decltype(foo) blubb; 

y su uso da como resultado un error de vinculador:

undefined reference to `Bar::blubb(int)' 

¿Este comportamiento es esperado?

+0

¿De verdad quieres el tipo de la función, o en su lugar las funciones devuelven el tipo (que puedes obtener "simulando" una llamada como 'decltype (foo (0))') –

+0

Diría que gcc aún no lo ha hecho implementado. Funciona bien en clang. – PlasmaHH

+0

@phresnel: mirando cómo lo invoca ('bar (6)') Supongo que quiere la función. Sin embargo, me pregunto si el error del enlazador es una queja (se espera cuando no se define la función), o simplemente para mostrar que creó la función muy bien. – PlasmaHH

Respuesta

5

Parece que desea "copiar" la firma de otra función para crear una función con la misma firma. Como decltype(foo) es de hecho el tipo de función (y no un puntero a esa función, que sería decltype(&foo) y llevaría a una declaración de puntero), puede usarla para declarar una función con la misma firma que otra función.

como lo indica el error de vinculador:

undefined reference to `Bar::blubb(int)' 

esto ya no tendrán ningún problema con su compilador. Sin embargo, parece que gcc aún no implementó completamente esta parte del estándar, ya que no aceptará la sintaxis para lo mismo con un operador de llamada de función. Clang por cierto. estará feliz de aceptarlo y el enlace a continuación, los errores con

undefined reference to `Bar::operator()(int)' 

Su pregunta acerca de por qué existe ese error enlazador indica una falta de comprensión de lo que lo hace realmente decltype.

Simplemente evaluará a un tipo, no más. La definición de blubb no está de ninguna manera vinculada a la definición de foo. Esto podría ser más clara cuando se escribe como si fuera

typedef decltype(foo) x; 
x blubb; 

Ahora puede alternativamente typedef x ser explícitamente el tipo de función, que no se modificaba en modo alguno lo que es blubb. Aún necesitas definirlo.Y puesto que no hay sintaxis para definirla usando decltype, usted tiene explícitamente a escribir como

int Bar::operator()(int) { 
... 
} 

que probablemente y desafortunadamente se anule el propósito/beneficio del uso de decltype para la declaración, ya que no le permitirá automáticamente "copia" una firma.

2

Esta es una suposición basada en la observación de su uso de printf aquí:

printf("%d\n",bar(6)); 

Esto me permite suponer que realmente quiere el tipo de retorno de la función, no el tipo de la función. Si es así, entonces usa decltype incorrecto. Se obtiene el tipo de retorno de la función de "simular" el uso de la función, es decir

decltype(foo(0)) operator() (int); 

debe ser lo correcto para usted. De lo contrario, si esa no era su atención, está patinando sobre hielo fino al asignar un tipo de función (y no un tipo de devolución de función) al especificador %d.

Generalmente, el significado de decltype es: decltype(@) proporciona el tipo estático de la expresión @.

+3

Teniendo en cuenta esa idea, tu solución debería ser (también pickung) el patrón de uso): 'decltype (foo (0)) operator() (int);' – PlasmaHH

+0

@PlasmaHH: Correcto, gracias. –

+0

Soy muy consciente del patrón 'habitual'. Esto no es lo que quise decir, vea mi primer comentario anterior. Aún así, su respuesta es probablemente lo que la mayoría de los usuarios realmente desean. – smilingthax

0

Esto debería funcionar. acabo de utilizar aquí para capturar todo lo gobbledygook std::bind me iba a dar:

class RiceFadingModel::Impl 
{ 
public: 
    Impl(double K, double A) 
    : //... 
    _M_re{system_now()}, 
    _M_rd{_M_nu, _M_sigma}, 
    _M_gen{std::bind(_M_rd, _M_re)} 
    { } 


private: 

//... 

    std::default_random_engine _M_re; 
    /// The underlying Rice distribution. 
    __gnu_cxx::__rice_distribution<double> _M_rd; 
    /// The variate generator built from the pseudo-random number engine and the Rice distribution. 
    decltype(std::bind(_M_rd, _M_re)) _M_gen; 
}; 

Esto funciona como un encanto en gcc-4.7. Ahora que lo pienso lo construí en mingw con gcc-4.5 también.

Cuestiones relacionadas