Llamar a la función miembro` this ' desde lambda - clang genérico vs gcc
Problema: pasar un lambda genérico (a una función de plantilla) que captura this
y llama a una función miembro de this
sin un this->
explícito no compila en gcc. Si la lambda no es genérica, o si la lambda no se pasa a ninguna otra función sino que se llama en su lugar, compila withoit un this->
explícito. Clang está bien con el código en todas las situaciones.
Tiempo para otra ronda de clang vs gcc. ¿Quién tiene razón?
template<typename TF>
void call(TF&& f)
{
f(1);
}
struct Example
{
void foo(int){ }
void bar()
{
call([this](auto x){ foo(x); });
}
};
int main()
{
Example{}.bar();
return 0;
}
- Con
bar()
=call([this](auto x){ foo(x); });
- clang++ 3.6+ compila.
- g++ 5.2+ no compila.
Error: no se puede llamar a la función miembro 'void Example:: foo (int)' sin objeto call ([this](auto x) { foo (x);}); '
- Con
bar()
=call([this](auto x){ this->foo(x); });
- clang++ 3.6+ compila.
- g++ 5.2+ compila.
- Con
bar()
=call([this](int x){ foo(x); });
- clang++ 3.6+ compila.
- g++ 5.2+ compila.
- Con
bar()
=[this](auto x){ foo(x); }(1);
- clang++ 3.6+ compila.
- g++ 5.2+ compila.
¿Por qué es necesario this->
solo en el caso de una lambda genérica?
¿Por qué no es necesario this->
si no se pasa la lambda a call
?
¿Quién no cumple con las normas?
1 answers
Este es un error de gcc. De [expr.prim.lambda]:
La lambda-expression ' s compound-statement produce el function-body (8.4) del operador de llamada a la función, pero para fines de búsqueda de nombres (3.4), determinar el tipo y el valor de
this
(9.3.2) y transformar id-expressions al referirse a los miembros de clase no estáticos en expresiones de acceso a miembros de clase usando(*this)
(9.3.1), la instrucción compuesta se considera en el contexto de la expresión lambda . [ Ejemplo:struct S1 { int x, y; int operator()(int); void f() { [=]()->int { return operator()(this->x + y); // equivalent to S1::operator()(this->x + (*this).y) // this has type S1* }; } };
-ejemplo final ]
Dado que en su ejemplo captura this
, la búsqueda de nombres debe incluir los miembros de la clase de Example
, que por lo tanto debe encontrar Example::foo
. La búsqueda realizada es idéntica a lo que sucedería si foo(x)
apareciera en el contexto de la propia expresión lambda, es decir, si el código se viera como:
void bar()
{
foo(x); // clearly Example::foo(x);
}
Al menos este error tiene un muy simple solución como se indica en la pregunta: simplemente haga this->foo(x);
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-19 14:50:01