C++ std:qualquer exemplos

C Std Qualquer Exemplos



Na programação C++, “std::any” da Standard Template Library (STL) introduz uma tipagem dinâmica para lidar com dados heterogêneos. Ao contrário dos contêineres tradicionais, “std::any” permite armazenar valores de qualquer tipo em um único contêiner, aumentando a flexibilidade em cenários onde os tipos de dados são desconhecidos ou variam em tempo de execução. Esta abordagem independente de tipo promove uma programação genérica que capacita os desenvolvedores a criar um código mais adaptável e expressivo, mantendo a segurança de tipo. Nesta exploração, nos aprofundaremos nos recursos de “std::any”, seus padrões de uso e exemplos práticos que ilustram seu papel na escrita de um código C++ robusto e flexível.

Exemplo 1: Uso Básico de Std::Any

Primeiro, vamos explorar um exemplo simples para demonstrar o uso fundamental de “std::any”. Considere um cenário onde você precisa de uma função para aceitar vários tipos de parâmetros:







Aqui está o trecho de código:



#include
#include

void processAny ( const std::qualquer & valor ) {
se ( valor.has_value ( ) ) {
std::cout << 'Tipo de valor armazenado:' << valor.tipo ( ) .nome ( ) << std::endl;

se ( valor.tipo ( ) == ID do tipo ( interno ) ) {
std::cout << 'Valor: ' << std::any_cast < interno > ( valor ) << std::endl;
} outro se ( valor.tipo ( ) == ID do tipo ( dobro ) ) {
std::cout << 'Valor: ' << std::any_cast < dobro > ( valor ) << std::endl;
} outro se ( valor.tipo ( ) == ID do tipo ( std::string ) ) {
std::cout << 'Valor: ' << std::any_cast < std::string > ( valor ) << std::endl;
} outro {
std::cout << 'Tipo não suportado!' << std::endl;
}
} outro {
std::cout << 'Nenhum valor armazenado em std::any.' << std::endl;
}
}

principal interno ( ) {
processAny ( 42 ) ;
processAny ( 3.14 ) ;
processAny ( std::string ( 'Olá, std::qualquer!' ) ) ;
processAny ( 4,5f ) ; // Não compatível tipo

retornar 0 ;
}


Neste exemplo, definimos a função “processAny” que recebe uma referência “std::any” como parâmetro e examina seu conteúdo. Dentro da função, primeiro verificamos se a variável “std::any” possui um valor armazenado usando has_value(). Se um valor estiver presente, determinamos o tipo do valor armazenado usando type().name() e procedemos à impressão do valor correspondente com base em seu tipo. A função principal então demonstra a utilidade de “processAny” chamando-o com diferentes tipos: um inteiro (42), um duplo (3.14) e uma string (“Hello, std::any!”). A função trata cada tipo adequadamente e imprime os respectivos valores. No entanto, ao tentar processar um número de ponto flutuante (4.5f), que não é suportado neste exemplo, o programa trata a situação normalmente, indicando que o tipo não é suportado.



A saída gerada é:






Isso mostra como “std::any” permite o tratamento dinâmico de vários tipos de dados, tornando-o uma ferramenta versátil para programação genérica em C++.

Exemplo 2: Armazenando os tipos definidos pelo usuário

O segundo exemplo explora como esse tipo dinâmico na Biblioteca de Modelos Padrão (STL) acomoda perfeitamente as estruturas de dados personalizadas. Focando em um tipo definido pelo usuário, a estrutura de pontos, mostramos como “std::any” lida com as instâncias de tais estruturas.



Aqui está o código:

#include
#include

classe MinhaClasse {
público:
Minha classe ( valor interno ) : dados ( valor ) { }

void printData ( ) const {
std::cout << 'Dados em MinhaClasse:' << dados << std::endl;
}

privado:
dados internos;
} ;

principal interno ( ) {
std::any anyObject = MinhaClasse ( 42 ) ;

se ( qualquerObject.has_value ( ) ) {
auto & minhaClassInstance = std::any_cast < Minha classe &> ( qualquerobjeto ) ;
minhaClassInstance.printData ( ) ;
} outro {
std::cout << 'Nenhum valor armazenado em std::any.' << std::endl;
}

retornar 0 ;
}


Neste trecho de código C++, criamos um exemplo simples para ilustrar o uso do tipo “std::any” com uma classe definida pelo usuário chamada “MyClass”. Dentro da classe, há uma variável de membro privada chamada “data” e um método público chamado printData() para exibir o valor desses dados. Um valor inteiro é passado e atribuído ao membro “data” no construtor.

Na função “main”, instanciamos um objeto de “MyClass” com valor inicial de 42 e depois o armazenamos na variável “std::any” chamada “anyObject”. Isso demonstra a capacidade de “std::any” de armazenar instâncias de classes definidas pelo usuário.

Em seguida, usamos uma instrução “if” para verificar se “anyObject” tem um valor usando o método has_value(). Se houver um valor, recuperamos o objeto armazenado usando “std::any_cast”. O “std::any_cast” é empregado com o argumento do modelo “MyClass&” para converter o objeto armazenado em uma referência de “MyClass”. Esta referência, “myClassInstance”, é então usada para chamar o método printData(), mostrando a capacidade de acessar e operar no tipo armazenado definido pelo usuário dentro de “std::any”.

Se nenhum valor for armazenado em “std::any”, imprimimos uma mensagem significando isso. Esta verificação condicional garante que lidaremos com os cenários onde a variável “std::any” pode estar vazia.

Aqui está o resultado:

Exemplo 3: Container de tipos mistos

Na programação, um “contêiner de tipo misto” refere-se a uma estrutura de dados que é capaz de conter elementos de diversos tipos de dados potencialmente não relacionados. Essa flexibilidade é valiosa ao lidar com cenários onde os tipos de dados são desconhecidos em tempo de compilação ou mudam dinamicamente durante a execução do programa. Em C++, “std::any” exemplifica esse conceito, permitindo a criação de um único contêiner para armazenar valores de diferentes tipos.

Vamos explorar um cenário onde criamos um contêiner que contém vários tipos:

#include
#include
#incluir

principal interno ( ) {

std::vetor < std::qualquer > mistoContainer;

mistoContainer.push_back ( 42 ) ;
mistoContainer.push_back ( 3.14 ) ;
mistoContainer.push_back ( std::string ( 'Olá' ) ) ;
mistoContainer.push_back ( verdadeiro ) ;

para ( const automático & elemento: mistoContainer ) {
se ( elemento.type ( ) == ID do tipo ( interno ) ) {
std::cout << 'Inteiro:' << std::any_cast < interno > ( elemento ) << std::endl;
} outro se ( elemento.type ( ) == ID do tipo ( dobro ) ) {
std::cout << 'Dobro: ' << std::any_cast < dobro > ( elemento ) << std::endl;
} outro se ( elemento.type ( ) == ID do tipo ( std::string ) ) {
std::cout << 'Corda: ' << std::any_cast < std::string > ( elemento ) << std::endl;
} outro se ( elemento.type ( ) == ID do tipo ( bool ) ) {
std::cout << 'Boleano: ' << std::any_cast < bool > ( elemento ) << std::endl;
} outro {
std::cout << 'Tipo desconhecido' << std::endl;
}
}

retornar 0 ;
}


Nesta ilustração, demonstramos o conceito de contêiner de tipo misto usando C++ e o recurso “std::any”. Criamos o “std::vector” chamado “mixedContainer” para servir como nosso contêiner para armazenar os elementos de diferentes tipos de dados. Usando a função “push_back”, preenchemos este contêiner com vários elementos, incluindo um inteiro (42), um duplo (3.14), uma string (“Hello”) e um booleano (true).

À medida que iteramos através do “mixedContainer” usando um loop “for”, empregamos a função type() para identificar o tipo de dados de cada elemento dinamicamente. Utilizando “std::any_cast”, extraímos e imprimimos os valores correspondentes com base em seus tipos. Por exemplo, se o elemento for do tipo “int”, nós o imprimimos como um número inteiro. Se for do tipo “duplo”, imprimimos como duplo e assim por diante.

Aqui está a saída gerada:

Exemplo 4: Tratamento de erros com Std::Any

O tratamento de erros ao usar “std::any” envolve verificar se o tipo é suportado ou se um valor está armazenado. Neste exemplo, demonstramos como lidar com os tipos não suportados:

#include
#include

principal interno ( ) {
std::any meuAny = 42 ;

tentar {

valor duplo = std::any_cast < dobro > ( meuQualquer ) ;
std::cout << 'Valor: ' << valor << std::endl;
} pegar ( const std::bad_any_cast & e ) {

std::cerr << 'Erro:' << e.o que ( ) << std::endl;
}

retornar 0 ;
}


Começamos inicializando a variável “std::any”, “myAny”, com o valor 42 do tipo inteiro. Dentro do bloco “try” subsequente, fazemos uma tentativa explícita de converter esse valor inteiro em um “double” usando a operação “std::any_cast”. No entanto, como o tipo real armazenado em “myAny” é um número inteiro, esta operação de conversão é inválida para um “double”, o que leva a um tipo incompatível.

Para gerenciar esse erro potencial normalmente, implementamos o tratamento de exceções com um bloco “catch” que é projetado para capturar o tipo de exceção específico de “std::bad_any_cast”. No caso de uma conversão malsucedida, o bloco “catch” é ativado e geramos uma mensagem de erro usando “std::cerr” para comunicar a natureza do erro. Essa estratégia de tratamento de erros garante que nosso programa possa lidar normalmente com as situações em que a tentativa de conversão de tipo entra em conflito com o tipo real que está armazenado na variável “std::any”.

Conclusão

Neste artigo, exploramos as aplicações de “std::any” em C++, um contêiner de tipo dinâmico que é introduzido em C++ para valores de diversos tipos. Demonstramos sua versatilidade por meio de vários exemplos, apresentando cenários que vão desde o uso básico até o manuseio de tipos definidos pelo usuário e coleções heterogêneas. Demonstramos sua aplicação prática em cenários onde o tipo de dados não é conhecido em tempo de compilação. Além disso, exploramos as técnicas de tratamento de erros, enfatizando a importância de gerenciar normalmente os tipos não suportados por meio do tratamento de exceções.