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.

Cómo provocar un error en tiempo de compilación si se llama a una sobrecarga específica de una función?

Según https://en.cppreference.com/w/cpp/string/basicstringview/basicstringview, la clase std::basic_string_view tiene 7 constructores sobrecargados. Solo me interesan 2 de ellos, ya que actualmente no utilizo el resto en mi código.

Estos son los constructores que me interesan:

constexpr basic_string_view( const CharT* s, size_type count );
constexpr basic_string_view( const CharT* s );

Necesito evitar que el código llame al segundo (debido a que podría causar un desbordamiento de búfer para búferes no terminados en nulo).

Tengo algo como esto:


#include <iostream> #include <sstream> #include <string> #include <array> void func( const std::string_view str ) { if ( str.empty( ) ) { return; } std::stringstream ss; if ( str.back( ) == '\0' ) { ss << str.data( ); } else { ss << std::string{ str }; } } int main() { std::array<char, 20=""> buffer { }; std::cin.getline( buffer.data( ), 20 ); const std::string_view sv { buffer.data( ), buffer.size( ) }; func( sv ); // debería estar permitido func( { buffer.data( ), buffer.size( ) } ); // debería estar permitido func( buffer.data( ) ); // ¡NO debería estar permitido! }

¿Cuál es la forma correcta de hacer esto?</char,>

Tags:  , ,

Answer

  1. Avatar for davy.ai

    El segundo constructor (basic_string_view(const CharT* s)) debe ser evitado porque asume que la cadena de entrada está terminada en nulo, lo cual puede causar desbordamiento de búfer para cadenas no terminadas en nulo. Para evitar que el código llame al segundo constructor, una posible solución es crear una función auxiliar que tome una cadena no terminada en nulo y la convierta en una cadena terminada en nulo antes de construir std::string_view. Aquí está el código modificado:

    #include <iostream>
    #include <sstream>
    #include <string>
    #include <array>
    
    constexpr std::string_view make_string_view(const char* s, std::size_t count)
    {
        return { s, count };
    }
    
    void func(const std::string_view str)
    {
        if (str.empty())
        {
            return;
        }
    
        std::stringstream ss;
    
        ss << str;
    }
    
    int main()
    {
        std::array<char, 20=""> buffer {};
        std::cin.getline(buffer.data(), 20);
    
        const std::string_view sv { buffer.data(), buffer.size() };
    
        func(sv); // debería ser permitido
        func(make_string_view(buffer.data(), buffer.size())); // debería ser permitido
        // func(buffer.data()); // ¡NO debería ser permitido!
    }
    

    La función make_string_view toma un puntero a una cadena (s) y un tamaño (count) y construye internamente una cadena terminada en nulo antes de crear un std::string_view usando el primer constructor. De esta manera, podemos asegurar que basic_string_view siempre se inicializa con una cadena terminada en nulo y que el constructor de cadena no terminada en nulo nunca se utiliza.</char,>

Comments are closed.