2011-10-25 8 views
16

Quiero encontrar el punto, que tiene la menor coordenada Y (si hay más de tales puntos, encuentre el que tenga X más pequeña). Al escribir con lambda:lambda return bool

std::min_element(begin, end, [](PointAndAngle& p1, PointAndAngle& p2) { 
     if (p1.first->y() < p2.first->y()) 
      return true; 
     else if (p1.first->y() > p2.first->y()) 
      return false; 
     else 
      return p1.first->x() < p2.first->x(); 
    } 

que estoy recibiendo:

error C3499: a lambda that has been specified to have a void return type cannot return a value 

¿cuál es la diferencia entre:

// works 
    std::min_element(begin, end, [](PointAndAngle& p1, PointAndAngle& p2) { 
     return p1.first->y() < p2.first->y(); 
    } 

y

// does not work 
    std::min_element(begin, end, [](PointAndAngle& p1, PointAndAngle& p2) { 
     if (p1.first->y() < p2.first->y()) 
      return true; 
     else 
      return false; 
    } 
+1

La construcción 'if (expresión) devuelve true; else return false; 'es fundamentalmente feo. El doble de feo si la expresión es realmente booleana. –

+3

@ MichaelKrelin-hacker: Es cierto, pero eso es _no_ por qué el compilador rechaza el último ejemplo. – MSalters

+1

MSalters, seguro, es por eso que comento y no respondo. Esta es la respuesta a la pregunta "¿cuál es la diferencia". Y esta es la principal diferencia;) –

Respuesta

13

El tipo de retorno de lambdas se puede inferir implícitamente, pero debe tener una sola declaración return para lograr esto; es por eso que su lambda "en funcionamiento" funciona (el tipo de retorno se infiere que es bool).

La solución de sehe explícitamente declara el tipo de devolución, por lo que también funciona bien.

Actualización:

El estándar C++ 11, §5.1.2/4 estados:

Si un lambda-expresión no incluye un trailing-retorno de tipo, es como si el retorno de tipo oscilante longitudinal indica el tipo siguiente:

  • Si el compuesto-declaración es de la f orm { return expression ; } el tipo de la expresión devuelta después de conversión lvalue-a-rvalue (4.1), conversión de matriz a puntero (4.2) y conversión de función a puntero (4.3);

  • de lo contrario, void.

Su lambda no-trabajo cae en la segunda categoría.

+0

Curiosamente, wikipedia también incluye * si todas las ubicaciones que devuelven un valor devuelven el mismo tipo cuando la expresión de retorno se pasa a través de 'decltype'. * En el conjunto de lambdas que puede omitir el tipo de retorno . Pero parece que, según el estándar, este no es el caso. – mackenir

+0

@mackenir: De hecho, antes de profundizar en el estándar, pensé que podría ser también una limitación del compilador (la respuesta original está redactada así, pero las modificaciones se publicaron muy pronto después de la publicación, por lo que no se registraron). Wikipedia definitivamente es técnicamente incorrecta allí. – Jon

+0

¿Por qué compró una copia del estándar C++ 11? No puedo encontrarlo para descargar gratis. – mackenir

12

Como se señaló Mike, si el cuerpo de lambda es una declaración de devolución única, entonces el tipo de devolución se deduce de eso (ver 5.1.2/4) (gracias Mike).

std::min_element(begin, end, [] (const PointAndAngle & p1, const PointAndAngle & p2) 
    -> bool 
{ 
    if (p1.first->y() < p2.first->y()) 
     return true; 
    else 
     return false; 
} 

Nota -> bool.

+0

Y probablemente también sea bueno tomar los argumentos por const-reference, ya que el algoritmo puede querer darle eso. –

+0

¡gracias! ¿no debería el '-> bool' estar después de() en lugar de []? – relaxxx

+0

Supongo que es porque en la forma simple de una línea, el cmpiler puede deducir fácilmente el tipo de devolución, que no podrá hacerlo una vez que introduzca un condicional. Aunque tienes razón, siempre es una buena idea ser explícito sobre el tipo de devolución. –