C2228 de error en la construcción de impulso :: objeto de función en la lista de argumento del constructor

StackOverflow https://stackoverflow.com/questions/992717

Pregunta

El siguiente código no compila en Visual C ++ 2005.

class SomeClass {
public: boost::function<void()> func;
        SomeClass(boost::function<void()> &func): func(func) { }
};

void someFunc() {
    std::cout << "someFunc" << std::endl;
}

int main() {
    SomeClass sc(boost::function<void()>(&someFunc));
    sc.func(); // error C2228: left of '.func' must have class/struct/union
    return 0;
}

Si pongo paréntesis alrededor del argumento del constructor SomeClass o construye el objeto impulso :: función fuera de la lista de argumentos que compila bien.

    SomeClass sc((boost::function<void()>(&someFunc)));
    // or
    boost::function<void()> f(&someFunc);
    SomeClass sc(f);

¿Cuál es el problema con el código anterior?

¿Fue útil?

Solución

Es una declaración de función para una función de tomar una referencia a un boost:function <void()> y devolviendo una SomeClass. Puede memorizar la siguiente regla, que resulta de aplicar a muchos otros casos de desambiguación. Puede encontrar descripciones de estos casos en la sección 8.2 del estándar de C ++.

  

Cualquier construcción que posiblemente podría ser una declaración será tomada como una declaración

Eso significa que, se tendrán la siguiente como una declaración de parámetros, con paréntesis superfluos

boost::function<void()>(&someFunc)

Si se quita los paréntesis, esto se convertirá en claro

boost::function<void()> &someFunc

Y por lo tanto, toda la declaración no declarará más un objeto, sino una función

SomeClass sc(boost::function<void()> &someFunc);

Para solucionarlo, utilice el elenco notación

SomeClass sc((boost::function<void()>)&someFunc);

O dicho de paréntesis alrededor de toda la expresión, como lo hizo.

Aquí es el estándar en todo su esplendor desde 8.2:

  

La ambigüedad que surge de la similitud entre una conversión de estilo de función y una declaración mencionada en 6.8 también puede ocurrir en el contexto de una declaración. En ese contexto, la elección es entre una declaración de función con un conjunto redundante de paréntesis alrededor de un nombre de parámetro y una declaración de objeto con una conversión de estilo de función que el inicializador. Al igual que para las ambigüedades mencionadas en 6.8, la resolución es considerar cualquier construcción que podría ser una declaración de una declaración. [Nota: una declaración se puede disambiguated explícitamente por una conversión de estilo de no funcionamiento, por un = para indicar inicialización o eliminando los paréntesis redundantes alrededor del nombre del parámetro. ]

Tenga en cuenta que para el control de precedencia, se le permite introducir paréntesis, casi en cualquier lugar, como en el siguiente

int (((((((a))))))) = 3;
int (*(pa)) = &a;

Otros consejos

Esto se conoce como "más irritantes Parse C ++ 's" (de una libro de Scott Meyers llama eficaz STL).

respondió anterior , el compilador prefiere interpretar la línea problemática como una declaración de la función.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top