es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

mingw vs msvc en la conversión implícita de literales de cadena

Tengo un std::variant de diferentes tipos, incluyendo int32_t, int64_t, float, double, std::string y bool.
Cuando asigno un literal de cadena (const char *, que no está presente en este variant), asumí que se convertiría implícitamente a std::string y funcionó como esperaba con MinGW (9.0.0 de 64 bits). Pero con MSVC (2019 de 64 bits), se convirtió implícitamente a bool.
Si lo convierto explícitamente a std::string y luego lo asigno al variant, funciona bien con ambos compiladores.

Aquí está el código:

#include <iostream>
#include <variant>

#if defined(__MINGW64__) || defined(__MINGW32__)
#define CMP_NAME "[ MinGW ]"
#elif defined(_MSC_VER)
#define CMP_NAME "[ MSVC ]"
#else
#define CMP_NAME "[ Others ]"
#endif

using KInt32 = int32_t;
using KInt64 = int64_t;
using KFloat = float;
using KDouble = double;
using KString = std::string;
using KBoolean = bool;

using Variant = std::variant<
    KInt32,      /*0*/
    KInt64,      /*1*/
    KFloat,      /*2*/
    KDouble,     /*3*/
    KString,     /*4*/
    KBoolean    /*5*/
> ;

int main()
{
    //passing a const char* to Variant [target is to initialize as KString]
    Variant var = "ABCDE";
    std::cout << "Build With Compiler Set " << CMP_NAME << std::endl;
    std::cout << "index = " << var.index() << std::endl;
    try {
        KString &str = std::get<kstring>(var);
        std::cout << "\t[string = " << str << "]" << std::endl;
    }
    catch (const std::exception &e) {
        std::cout << "\t[exception = " << e.what() << "]" << std::endl;
    }
    return 0;
}

Aquí está la salida:
Con MinGW 9.0.0

     Build With Compiler Set [ MSVC ]
     index = 5
          [exception = bad variant access]

Con MSVC 2019

Build With Compiler Set [ MinGW ]
index = 4
    [string = ABCDE]

El índice 4 denota a KString (también conocido como std::string) y el 5 denota a KBoolean (también conocido como bool).
Entonces mi pregunta es ¿por qué ambos compiladores dan resultados diferentes?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    La razón por la que ambos compiladores están dando resultados diferentes se debe a la implementación diferente de la clase std::variant en los dos compiladores.

    Según el estándar C++17, cuando se pasa un literal de cadena a un objeto std::variant que tiene un tipo std::string como una de sus alternativas, el literal de cadena debe convertirse implícitamente en std::string. Sin embargo, el estándar no especifica qué debería suceder si se pasa un literal de cadena a un objeto std::variant que no tiene std::string como una de sus alternativas.

    Por ejemplo, en el caso de MSVC, parece que la implementación permite que el literal de cadena se convierta implícitamente en bool, que es la última alternativa en el objeto Variant. Por otro lado, en el caso de MinGW, parece que la implementación intenta hacer coincidir el literal de cadena con la alternativa std::string del objeto Variant, como se esperaba.

    Por lo tanto, es importante siempre convertir explícitamente un literal de cadena en std::string antes de asignarlo a un objeto std::variant para garantizar el comportamiento correcto en diferentes compiladores.

Comments are closed.