Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

275
Vistas
El operador ternario aplicado a diferentes lambdas produce resultados inconsistentes

Considere lo siguiente que usa el operador ternario para obtener el tipo de puntero de función común de las dos lambdas

 int main() { true ? [](auto) noexcept {} : [](int) {}; }

GCC-trunk solo lo acepta en C++14 pero lo rechaza en C++17/20 con ( Demo ):

 <source>:2:8: error: operands to '?:' have different types 'main()::<lambda(auto:1)>' and 'main()::<lambda(int)>' 2 | true ? [](auto) noexcept {} : [](int) {}; | ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Clang-trunk lo acepta en todos los modos C++14/17/20 ( Demo ).

MSVC-trunk solo lo acepta en C++20 pero lo rechaza en C++14/17 con ( Demo ):

 <source>(2): error C2446: ':': no conversion from 'main::<lambda_01e5bb79b5a210014fb78333f6af80f9>' to 'main::<lambda_57cf6f5767bc1bee4c1e1d9859a585d2>' <source>(2): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

¿Qué compilador es el correcto?

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Dado que cada expresión lambda tiene un tipo único y ninguna expresión lambda se puede convertir en otra, se aplica [expr.cond]/6 .

Si el segundo y el tercer operando no tienen el mismo tipo, y cualquiera tiene un tipo de clase (posiblemente cv calificado), la resolución de sobrecarga se usa para determinar las conversiones (si las hay) que se aplicarán a los operandos ([over.match.oper ], [sobreconstruido]). Si la resolución de sobrecarga falla, el programa está mal formado. De lo contrario, se aplican las conversiones así determinadas y los operandos convertidos se usan en lugar de los operandos originales para el resto de esta subcláusula.

Los candidatos son ( [over.built]/25 ):

Para cada tipo T , donde T es un puntero, puntero a miembro o tipo de enumeración con ámbito, existen funciones de operador candidatas de la forma

 T operator?:(bool, T, T);

Creo que la resolución de sobrecarga debería tener éxito en este caso y, como resultado, ambos operandos deberían convertirse en void(*)(int) .

Es decir, IMO clang es correcto.


Editar: creo que [](auto) noexcept {} es convertible a void(*)(int) , porque tiene una plantilla de función de conversión template<class T> operator FP() , donde FP es void(*)(T) ( [expr.prim.lambda.cierre]/9 ).

Para una lambda genérica sin captura de lambda, el tipo de cierre tiene una plantilla de función de conversión para apuntar a la función. La plantilla de función de conversión tiene la misma lista de parámetros de plantilla inventada, y el puntero a función tiene los mismos tipos de parámetros que la plantilla de operador de llamada de función. El tipo de retorno del puntero a la función se comportará como si fuera un especificador de tipo de declinación que denota el tipo de retorno de la especialización de plantilla de operador de llamada de función correspondiente.

Y creo que la deducción del argumento de la plantilla debería hacer que esta plantilla de conversión se pueda utilizar como una conversión a void(*)(int) ( [temp.deduct.conv]/5 ).

La deducción del argumento de la plantilla se realiza comparando el tipo de retorno de la plantilla de la función de conversión (llámela P ) con el tipo especificado por el id del tipo de conversión de la id de la función de conversión que se busca (llámela A ) como se describe en [ temp.deduct.type].

[...]

En general, el proceso de deducción intenta encontrar valores de argumentos de plantilla que hagan que la A deducida sea idéntica a A . Sin embargo, ciertos atributos de A pueden ignorarse:

  • [...]
  • Si el A original es un puntero de función o un tipo de función de puntero a miembro, es noexcept .
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda