c++ - iterativa - fibonacci iterativo java
Llamada recursiva en lambda(C++ 11) (3)
Como lo veo, la diferencia importante entre el caso auto a
y la std::function<void()> a
es que el tipo std::function<void()>
no sabe / importa cuál es el tipo de La función real a la que se refiere realmente es. Escritura:
std::function<void()> a;
está perfectamente bien, donde como:
auto a;
tiene poco sentido Entonces, cuando llegue el momento de sintetizar la captura, si usa std::function<void()>
todo lo que se necesita saber sobre el tipo ya se conoce, mientras que con auto
aún no se conoce.
Posible duplicado:
Funciones lambda recursivas en c ++ 0x
¿Por qué no puedo llamar a un lambda recursivamente si lo escribo como:
auto a = [&]
{
static int i = 0; i++;
std::cout << i << std::endl;
if (i<10)
a(); //recursive call
};
Da error de compilación ( ideone ):
prog.cpp:8:18: error: ''((const main()::<lambda()>*)this)->main()::<lambda()>::a'' cannot be used as a function
prog.cpp: In function ''int main()'':
prog.cpp:9:9: error: variable ''auto a'' with ''auto'' type used in its own initializer
¿Qué significa el error?
Entiendo la razón por la que no puedo escribir esto:
auto i=i+1; //error: unable to deduce ''auto'' from ''<expression error>''
No podemos escribir esto porque el tipo de i
debe deducirse desde su inicialización, lo que significa que el tipo no puede deducirse si i
mismo aparece en la inicialización ( ideone ). Pero, ¿qué importa en caso de lambda? Si no estoy equivocado, el tipo de un lambda está determinado por sus parámetros y el tipo de retorno; no depende del cuerpo si no devuelve nada (en cuyo caso, el tipo de devolución se deduce como void
, independientemente de otras declaraciones en la lambda-cuerpo).
De todos modos, tengo una solución alternativa y puedo usar std::function
lugar como:
std::function<void()> a = [&]
{
static int i = 0; i++;
std::cout << i << std::endl;
if (i<10)
a();
};
que compilan multas ( ideone ). Pero todavía me interesa saber por qué la versión auto
no se compila.
En una función recursiva, f
se define por f
y el tipo de retorno de f
también se determina por f
en caso de auto
por lo que conduce a una recursión infinita.
Cuando auto
trata de derivar un tipo. decltype (f ()) deducirá aún más a otro decltype (f) `como f deriva a f, por ejemplo, una llamada a cualquier cosa recursiva también es recursiva. la determinación del tipo de retorno se vuelve recursiva cuando se aplica en una función recursiva. en una función recursiva, el final de la recursión se puede hacer en tiempo de ejecución. pero la determinación es solo estática
La razón es que no hay un caso especial para los inicializadores de lambda-expresión de variables auto
.
Tales casos especiales serían propensos a errores y mal uso. Debe definir las reglas cuando proponga que algo como a()
funcione. ¿Cómo se ve el operator()
? ¿Cuál es el estado preciso de a
tipo? ¿Estará completo el tipo? (lo que implica que ya conoce la lista de captura de la lambda). Una vez que haya formulado eso en un formato razonable para una especificación, sería más fácil hacer declaraciones sobre él.
Permitir su caso de uso significaría otro caso en el que necesita escanear con anticipación el código, porque para determinar el tipo de a
en a()
debe asegurarse de que el inicializador finalice con nada que pueda "desmarcar" el tipo
struct y { void operator()() { } };
template<typename T> y operator+(T, y) { return y(); }
auto x = [] { x(); } + y();
En este caso, x()
llamaría y::operator()
, no lambda.
Tal como está ahora, simplemente está prohibido que se mencione en su inicializador completo. Porque en C ++, auto
no es un tipo. Es simplemente un especificador de tipo que representa un tipo a deducir. Como consecuencia, una expresión nunca puede tener el tipo auto .