Eu gostaria de poder examinar uma classe C ++ por seu nome, conteúdo (por exemplo, membros e seus tipos) etc. Estou falando de C ++ nativo aqui, não de C ++ gerenciado, que tem reflexão. Sei que o C ++ fornece algumas informações limitadas usando o RTTI. Quais bibliotecas adicionais (ou outras técnicas) poderiam fornecer essas informações?
c++
reflection
templates
sfinae
usuario
fonte
fonte
Respostas:
O que você precisa fazer é fazer com que o pré-processador gere dados de reflexão sobre os campos. Esses dados podem ser armazenados como classes aninhadas.
Primeiro, para tornar mais fácil e mais limpo escrevê-lo no pré-processador, usaremos a expressão digitada. Uma expressão digitada é apenas uma expressão que coloca o tipo entre parênteses. Então, em vez de escrever,
int x
você escreverá(int) x
. Aqui estão algumas macros úteis para ajudar com expressões digitadas:Em seguida, definimos uma
REFLECTABLE
macro para gerar os dados sobre cada campo (mais o próprio campo). Essa macro será chamada assim:Portanto, usando o Boost.PP , iteramos sobre cada argumento e geramos os dados desta maneira:
O que isso faz é gerar uma constante
fields_n
que é o número de campos refletíveis na classe. Em seguida, ele é especializadofield_data
para cada campo. Também é amigo dareflector
turma, para que ele possa acessar os campos mesmo quando privados:Agora, para iterar sobre os campos, usamos o padrão de visitante. Criamos um intervalo de MPL de 0 ao número de campos e acessamos os dados do campo nesse índice. Em seguida, ele passa os dados do campo para o visitante fornecido pelo usuário:
Agora, no momento da verdade, reunimos tudo. Aqui está como podemos definir uma
Person
classe que é refletível:Aqui está uma
print_fields
função generalizada usando os dados de reflexão para iterar sobre os campos:Um exemplo de uso de
print_fields
com aPerson
classe refletível :Quais saídas:
E pronto, acabamos de implementar a reflexão em C ++, em menos de 100 linhas de código.
fonte
#define DETAIL_TYPEOF_INT2(tuple) DETAIL_TYPEOF_HEAD tuple
e#define DETAIL_TYPEOF_INT(...) DETAIL_TYPEOF_INT2((__VA_ARGS__))
e alterando a definição de typeof (x):#define TYPEOF(x) DETAIL_TYPEOF_INT(DETAIL_TYPEOF_PROBE x,)
Existem dois tipos de
reflection
natação ao redor.Isso não é possível com o C ++.
Esse tipo de coisa é possível com o C ++ usando
template-tricks
. Useboost::type_traits
para muitas coisas (como verificar se um tipo é integral). Para verificar a existência de uma função membro, use É possível escrever um modelo para verificar a existência de uma função? . Para verificar se existe um determinado tipo aninhado, use SFINAE simples .Se você está procurando maneiras de realizar 1), como procurar quantos métodos uma classe possui ou como obter a representação de string de um ID de classe, receio que não haja uma maneira C ++ padrão de fazer isso. Você tem que usar
C ++ é feito com velocidade em mente. Se você deseja uma inspeção de alto nível, como C # ou Java, receio dizer que não há maneira sem esforço.
fonte
members<T>
que retorna uma lista de todos os membros de T. Se quiséssemos ter reflexão em tempo de execução (isto é, RTTI misturado com reflexão), o compilador ainda saberia todos os tipos de base refletidos. Provavelmentemembers<T>(T&)
, nunca seria instanciado para T = std :: string, portanto, o RTTI para std :: string ou suas classes derivadas não precisam ser incluídas.E eu adoraria um pônei, mas os pôneis não são livres. :-p
http://en.wikibooks.org/wiki/C%2B%2B_Programming/RTTI é o que você obterá. Reflexões como você está pensando - metadados totalmente descritivos disponíveis em tempo de execução - simplesmente não existem para C ++ por padrão.
fonte
As informações existem - mas não no formato que você precisa e somente se você exportar suas classes. Isso funciona no Windows, não conheço outras plataformas. Usando os especificadores da classe de armazenamento como em, por exemplo:
Isso faz com que o compilador crie os dados de definição de classe na DLL / Exe. Mas não está em um formato que você possa usar prontamente para reflexão.
Na minha empresa, construímos uma biblioteca que interpreta esses metadados e permite refletir uma classe sem inserir macros extras etc. na própria classe. Permite que as funções sejam chamadas da seguinte maneira:
Isso efetivamente faz:
A função Invoke (this_pointer, ...) possui argumentos variáveis. Obviamente, chamando uma função dessa maneira, você está contornando coisas como const-safety e assim por diante, para que esses aspectos sejam implementados como verificações de tempo de execução.
Tenho certeza de que a sintaxe pode ser aprimorada, e só funciona no Win32 e Win64 até agora. Nós achamos realmente útil ter interfaces GUI automáticas para classes, criar propriedades em C ++, transmitir de e para XML e assim por diante, e não é necessário derivar de uma classe base específica. Se houver demanda suficiente, talvez possamos colocá-lo em forma para lançamento.
fonte
__declspec(dllexport)
e você pode recuperar as informações de um arquivo .map se você habilitar a criação de tais durante a compilação.A reflexão não é suportada pelo C ++ imediatamente. Isso é triste, porque faz do teste defensivo uma dor.
Existem várias abordagens para refletir:
O primeiro link parece o mais promissor (usa mod's para clang), o segundo discute várias técnicas, o terceiro é uma abordagem diferente usando o gcc:
http://www.donw.org/rfl/
https://bitbucket.org/dwilliamson/clreflect
https://root.cern.ch/how/how-use-reflex
Agora existe um grupo de trabalho para reflexão em C ++. Veja as notícias do C ++ 14 @ CERN:
Editar 13/08/17:
Desde o post original, houve vários avanços em potencial na reflexão. A seguir, são fornecidos mais detalhes e uma discussão sobre as várias técnicas e status:
No entanto, não parece promissor em uma abordagem padronizada de reflexões em C ++ em um futuro próximo, a menos que haja muito mais interesse da comunidade em apoiar a reflexão em C ++.
A seguir, detalha o status atual com base nos comentários da última reunião de padrões de C ++:
Editar 13/12/2017
A reflexão parece estar se movendo em direção a C ++ 20 ou mais, provavelmente um TSR. O movimento é contudo lento.
Editar 15/09/2018
Um projeto de TS foi enviado aos órgãos nacionais para votação.
O texto pode ser encontrado aqui: https://github.com/cplusplus/reflection-ts
Editar 11/07/2019
A reflexão TS é um recurso completo e está fora para comentários e votação durante o verão (2019).
A abordagem de programação de meta-modelos deve ser substituída por uma abordagem mais simples de código de tempo de compilação (não refletida no TS).
Editar 10/02/2020
Há uma solicitação para oferecer suporte à reflexão TS no Visual Studio aqui:
Fale sobre o TS pelo autor David Sankel:
http://cppnow.org/history/2019/talks/
https://www.youtube.com/watch?v=VMuML6vLSus&feature=youtu.be
Editar 17 de março de 2020
Progresso na reflexão está sendo feito. Um relatório do 'Relatório de viagem do comitê ISO C ++ 2020-02 de Praga' pode ser encontrado aqui:
Detalhes sobre o que está sendo considerado para o C ++ 23 podem ser encontrados aqui (inclui uma breve seção sobre Reflexão):
Editar 4 de junho de 2020
Uma nova estrutura foi lançada por Jeff Preshing chamada 'Plywood' que contém um mecanismo para reflexão em tempo de execução. Mais detalhes podem ser encontrados aqui:
As ferramentas e a abordagem parecem ser as mais polidas e mais fáceis de usar até agora.
fonte
Você precisa analisar o que está tentando fazer e se o RTTI atenderá aos seus requisitos. Eu implementei minha própria pseudo-reflexão para alguns propósitos muito específicos. Por exemplo, uma vez eu queria poder configurar com flexibilidade o que uma simulação produziria. É necessário adicionar algum código padrão às classes que seriam produzidas:
A primeira chamada adiciona esse objeto ao sistema de filtragem, que chama o
BuildMap()
método para descobrir quais métodos estão disponíveis.Então, no arquivo de configuração, você pode fazer algo assim:
Por meio de alguma mágica envolvendo modelos
boost
, isso é traduzido em uma série de chamadas de método em tempo de execução (quando o arquivo de configuração é lido), por isso é bastante eficiente. Eu não recomendaria fazer isso, a menos que você realmente precise, mas, quando precisar, poderá fazer algumas coisas bem legais.fonte
Eu recomendaria usar o Qt .
Existe uma licença de código-fonte aberto e também uma licença comercial.
fonte
O que você está tentando fazer com a reflexão?
Você pode usar as características do tipo Boost e o tipo de bibliotecas como uma forma limitada de reflexão em tempo de compilação. Ou seja, você pode inspecionar e modificar as propriedades básicas de um tipo passado para um modelo.
fonte
EDIT : CAMP não é mais mantido; dois garfos estão disponíveis:
CAMP é uma biblioteca licenciada do MIT (anteriormente LGPL) que adiciona reflexão à linguagem C ++. Não requer uma etapa específica de pré-processamento na compilação, mas a ligação deve ser feita manualmente.
A atual biblioteca Tegesoft usa o Boost, mas também há um fork usando o C ++ 11 que não requer mais o Boost .
fonte
Fiz algo parecido com o que você procura uma vez e, embora seja possível obter algum nível de reflexão e acesso a recursos de nível superior, a dor de cabeça na manutenção pode não valer a pena. Meu sistema foi usado para manter as classes de interface do usuário completamente separadas da lógica de negócios por meio de delegação semelhante ao conceito de Objective-C de passagem e encaminhamento de mensagens. A maneira de fazer isso é criar alguma classe base capaz de mapear símbolos (usei um pool de strings, mas você poderia fazê-lo com enumerações, se preferir velocidade e manipulação de erros em tempo de compilação, em vez de flexibilidade total) para funcionar como ponteiros (na verdade não ponteiros de função pura, mas algo semelhante ao que o Boost possui com o Boost.Function - ao qual eu não tinha acesso no momento). Você pode fazer o mesmo com suas variáveis de membro, desde que tenha alguma classe base comum capaz de representar qualquer valor. Todo o sistema era uma imitação descarada da codificação e delegação de valores-chave, com alguns efeitos colaterais que talvez valessem a quantidade de tempo necessária para que todas as classes que usassem o sistema combinassem todos os seus métodos e membros com chamadas legais : 1) Qualquer classe poderia chamar qualquer método em qualquer outra classe sem precisar incluir cabeçalhos ou escrever classes base falsas, para que a interface pudesse ser predefinida para o compilador; e 2) Os getters e setters das variáveis membro eram fáceis de tornar seguros para threads, pois a alteração ou o acesso a seus valores sempre era feita através de 2 métodos na classe base de todos os objetos. Todo o sistema era uma imitação descarada da codificação e delegação de valores-chave, com alguns efeitos colaterais que talvez valessem a quantidade de tempo necessária para que todas as classes que usassem o sistema combinassem todos os seus métodos e membros com chamadas legais : 1) Qualquer classe poderia chamar qualquer método em qualquer outra classe sem precisar incluir cabeçalhos ou escrever classes base falsas, para que a interface pudesse ser predefinida para o compilador; e 2) Os getters e setters das variáveis membro eram fáceis de tornar seguros para threads, pois a alteração ou o acesso a seus valores sempre era feita através de 2 métodos na classe base de todos os objetos. Todo o sistema era uma imitação descarada da codificação e delegação de valores-chave, com alguns efeitos colaterais que talvez valessem a quantidade de tempo necessária para que todas as classes que usassem o sistema combinassem todos os seus métodos e membros com chamadas legais : 1) Qualquer classe poderia chamar qualquer método em qualquer outra classe sem precisar incluir cabeçalhos ou escrever classes base falsas, para que a interface pudesse ser predefinida para o compilador; e 2) Os getters e setters das variáveis membro eram fáceis de tornar seguros para threads, pois a alteração ou o acesso a seus valores sempre era feita através de 2 métodos na classe base de todos os objetos. 1) Qualquer classe poderia chamar qualquer método em qualquer outra classe sem precisar incluir cabeçalhos ou escrever classes base falsas, para que a interface pudesse ser predefinida para o compilador; e 2) Os getters e setters das variáveis-membro eram fáceis de tornar seguros para threads, pois a alteração ou acesso a seus valores sempre era feita através de 2 métodos na classe base de todos os objetos. 1) Qualquer classe poderia chamar qualquer método em qualquer outra classe sem precisar incluir cabeçalhos ou escrever classes base falsas, para que a interface pudesse ser predefinida para o compilador; e 2) Os getters e setters das variáveis membro eram fáceis de tornar seguros para threads, pois a alteração ou o acesso a seus valores sempre era feita através de 2 métodos na classe base de todos os objetos.
Também levou à possibilidade de fazer coisas realmente estranhas que, de outra forma, não são fáceis em C ++. Por exemplo, eu poderia criar um objeto Array que continha itens arbitrários de qualquer tipo, inclusive ele próprio, e criar novas matrizes dinamicamente passando uma mensagem para todos os itens da matriz e coletando os valores de retorno (semelhante ao mapa no Lisp). Outra foi a implementação da observação de valores-chave, na qual eu consegui configurar a interface do usuário para responder imediatamente às alterações nos membros das classes de back-end, em vez de pesquisar constantemente os dados ou redesenhar desnecessariamente a exibição.
Talvez o mais interessante para você seja o fato de que você também pode despejar todos os métodos e membros definidos para uma classe, e na forma de string não menos.
Desvantagens do sistema que podem desencorajar você de se incomodar: adicionar todas as mensagens e valores-chave é extremamente entediante; é mais lento do que sem qualquer reflexão; você vai crescer a odiar ver
boost::static_pointer_cast
eboost::dynamic_pointer_cast
toda a sua base de código com uma paixão violenta; as limitações do sistema fortemente tipado ainda existem, você realmente as esconde um pouco, para que não seja tão óbvio. Erros de digitação em suas cordas também não são divertidos ou fáceis de descobrir surpresa.Quanto à implementação de algo assim: basta usar ponteiros compartilhados e fracos para alguma base comum (a minha era muito imaginativamente chamada de "Objeto") e derivar para todos os tipos que você deseja usar. Eu recomendo instalar o Boost.Function em vez de fazê-lo da maneira que eu fiz, com algumas porcarias personalizadas e uma tonelada de macros feias para quebrar as chamadas do ponteiro de função. Como tudo é mapeado, a inspeção de objetos é apenas uma questão de iterar por todas as chaves. Como minhas aulas eram essencialmente o mais próximo possível de uma cópia direta do Cocoa usando apenas C ++, se você quiser algo assim, sugiro usar a documentação do Cocoa como um modelo.
fonte
Há outra nova biblioteca para reflexão em C ++, chamada RTTR (Run Time Type Reflection, veja também github ).
A interface é semelhante à reflexão em C # e funciona sem nenhum RTTI.
fonte
As duas soluções de reflexão que conheço nos meus dias em C ++ são:
1) Use RTTI, que fornecerá um bootstrap para você criar seu comportamento de reflexão, se você conseguir que todas as suas classes derivem de uma classe base de 'objeto'. Essa classe pode fornecer alguns métodos como GetMethod, GetBaseClass etc. Quanto ao modo como esses métodos funcionam, você precisará adicionar manualmente algumas macros para decorar seus tipos, que nos bastidores criam metadados no tipo para fornecer respostas para GetMethods etc.
2) Outra opção, se você tiver acesso aos objetos do compilador, é usar o DIA SDK . Se bem me lembro, isso permite abrir pdbs, que deve conter metadados para seus tipos de C ++. Pode ser o suficiente para fazer o que você precisa. Esta página mostra como você pode obter todos os tipos de base de uma classe, por exemplo.
Ambas as soluções são um pouco feias! Não há nada como um pouco de C ++ para fazer você apreciar os luxos do C #.
Boa sorte.
fonte
EDIT: link quebrado atualizado a partir de 7 de fevereiro de 2017.
Eu acho que ninguém mencionou isso:
No CERN, eles usam um sistema de reflexão completo para C ++:
Reflex do CERN . Isso parece funcionar muito bem.
fonte
Esta pergunta é um pouco antiga agora (não sei por que continuo respondendo a perguntas antigas hoje), mas eu estava pensando em BOOST_FUSION_ADAPT_STRUCT, que introduz a reflexão em tempo de compilação.
Cabe a você mapear isso para a reflexão em tempo de execução, é claro, e não será muito fácil, mas é possível nessa direção, embora não seja o contrário :)
Eu realmente acho que uma macro para encapsular
BOOST_FUSION_ADAPT_STRUCT
aquela poderia gerar os métodos necessários para obter o comportamento em tempo de execução.fonte
Eu acho que você pode achar interessante o artigo "Usando modelos para reflexão em C ++", de Dominic Filion. Está na seção 1.4 das Gemas de Programação de Jogos 5 . Infelizmente, não tenho minha cópia comigo, mas procure-a porque acho que explica o que você está pedindo.
fonte
Ponder é uma biblioteca de reflexão em C ++, em resposta a esta pergunta. Eu considerei as opções e decidi fazer as minhas próprias, pois não consegui encontrar uma que marque todas as minhas caixas.
Embora haja ótimas respostas para essa pergunta, não quero usar toneladas de macros ou confiar no Boost. O Boost é uma ótima biblioteca, mas existem muitos projetos C ++ 0x personalizados, mais simples e com tempos de compilação mais rápidos. Também há vantagens em poder decorar uma classe externamente, como agrupar uma biblioteca C ++ que ainda não suporta C ++ 11. É o fork do CAMP, usando C ++ 11, que não requer mais o Boost .
fonte
A reflexão é essencialmente sobre o que o compilador decidiu deixar como pegadas no código que o código de tempo de execução pode consultar. C ++ é famoso por não pagar pelo que você não usa; porque a maioria das pessoas não usa / deseja reflexão, o compilador C ++ evita o custo por não gravar nada .
Portanto, o C ++ não fornece reflexão e não é fácil "simular" você mesmo como regra geral, como outras respostas observaram.
Em "outras técnicas", se você não tiver um idioma com reflexão, obtenha uma ferramenta que possa extrair as informações desejadas em tempo de compilação.
Nosso DMS Software Reengineering Toolkit é uma tecnologia generalizada de compilador, parametrizada por definições explícitas de linguagem. Possui definições de idioma para C, C ++, Java, COBOL, PHP, ...
Para versões C, C ++, Java e COBOL, fornece acesso completo a árvores de análise e informações da tabela de símbolos. As informações da tabela de símbolos incluem o tipo de dados que você provavelmente deseja da "reflexão". Se seu objetivo é enumerar algum conjunto de campos ou métodos e fazer algo com eles, o DMS pode ser usado para transformar o código de acordo com o que você encontra nas tabelas de símbolos de maneira arbitrária.
fonte
Você pode encontrar outra biblioteca aqui: http://www.garret.ru/cppreflection/docs/reflect.html Ele suporta duas maneiras: obter informações de tipo das informações de depuração e permitir que o programador forneça essas informações.
Também me interessei em refletir sobre o meu projeto e encontrei esta biblioteca, ainda não tentei, mas tentei outras ferramentas desse cara e gosto de como elas funcionam :-)
fonte
Confira Classdesc http://classdesc.sf.net . Ele fornece reflexão na forma da classe "descritores", funciona com qualquer compilador C ++ padrão (sim, é conhecido por funcionar com o Visual Studio e o GCC) e não requer anotação de código-fonte (embora existam pragmas para lidar com situações complicadas) ) Está em desenvolvimento há mais de uma década e é usado em vários projetos em escala industrial.
fonte
Quando eu queria reflexão em C ++, li este artigo e aprimorei o que vi lá. Desculpe, não pode ter. Eu não possuo o resultado ... mas você certamente pode obter o que eu tinha e partir daí.
Atualmente, estou pesquisando, quando me apetece, métodos para usar o herdit_linearly para facilitar a definição de tipos refletíveis. Na verdade, cheguei bastante longe, mas ainda tenho um longo caminho a percorrer. As alterações no C ++ 0x provavelmente ajudarão bastante nessa área.
fonte
Parece que o C ++ ainda não possui esse recurso. E o C ++ 11 adiou a reflexão também ((
Pesquise algumas macros ou crie suas próprias. O Qt também pode ajudar na reflexão (se puder ser usado).
fonte
mesmo que o reflexo não seja suportado imediatamente no c ++, não é muito difícil de implementar. Encontrei este ótimo artigo: http://replicaisland.blogspot.co.il/2010/11/building-reflective-object-system-in-c.html
o artigo explica em detalhes como você pode implementar um sistema de reflexão bastante simples e rudimentar. concedida não é a solução mais saudável, e ainda há arestas a serem resolvidas, mas para as minhas necessidades foi suficiente.
a linha inferior - a reflexão pode render se feita corretamente, e é completamente viável em c ++.
fonte
Gostaria de anunciar a existência do kit de ferramentas de introspecção / reflexão automático "IDK". Ele usa um meta-compilador como o Qt e adiciona informações meta diretamente nos arquivos de objeto. Alega-se ser fácil de usar. Sem dependências externas. Ele ainda permite refletir automaticamente std :: string e usá-lo em scripts. Por favor, olhe para o IDK
fonte
Se você está procurando uma reflexão C ++ relativamente simples - eu coletei de várias fontes macro / define e comentei como elas funcionam. Você pode baixar os arquivos de cabeçalho aqui:
https://github.com/tapika/TestCppReflect/blob/master/MacroHelpers.h
conjunto de definições, além de funcionalidade:
https://github.com/tapika/TestCppReflect/blob/master/CppReflect.h https://github.com/tapika/TestCppReflect/blob/master/CppReflect.cpp https://github.com/tapika/TestCppReflect/ blob / master / TypeTraits.h
O aplicativo de amostra também reside no repositório git, aqui: https://github.com/tapika/TestCppReflect/
Vou copiá-lo parcialmente aqui com explicação:
REFLECTABLE
define usa o nome da classe + o nome do campo comoffsetof
- para identificar em qual local da memória um campo específico está localizado. Eu tentei pegar a terminologia .NET o máximo possível, mas C ++ e C # são diferentes, portanto, não é 1 para 1. Todo o modelo de reflexão C ++ reside emTypeInfo
eFieldInfo
classes.Eu usei o pugi xml parser para buscar o código de demonstração no xml e restaurá-lo novamente a partir do xml.
Portanto, a saída produzida pelo código de demonstração fica assim:
Também é possível ativar qualquer suporte de classe / estrutura de terceiros por meio da classe TypeTraits e especificação parcial de modelo - para definir sua própria classe TypeTraitsT, da mesma maneira que CString ou int - consulte o código de exemplo em
https://github.com/tapika/TestCppReflect/blob/master/TypeTraits.h#L195
Esta solução é aplicável ao Windows / Visual studio. É possível portá-lo para outros SO / compiladores, mas não o fez. (Pergunte-me se você realmente gosta de solução, posso ajudá-lo)
Esta solução é aplicável para serialização instantânea de uma classe com várias subclasses.
Se, no entanto, você estiver procurando por um mecanismo para serializar partes da classe ou mesmo para controlar o que as chamadas de reflexão de funcionalidade produzem, dê uma olhada na seguinte solução:
https://github.com/tapika/cppscriptcore/tree/master/SolutionProjectModel
Informações mais detalhadas podem ser encontradas no vídeo do youtube:
Reflexão do tipo de tempo de execução C ++ https://youtu.be/TN8tJijkeFE
Estou tentando explicar um pouco mais sobre como a reflexão em c ++ funcionará.
O código de exemplo será parecido com, por exemplo:
https://github.com/tapika/cppscriptcore/blob/master/SolutionProjectModel/testCppApp.cpp
Mas cada etapa aqui realmente resulta em chamada de função Using C ++ properties with
__declspec(property(get =, put ... )
.que recebe informações completas sobre tipos de dados C ++, nomes de propriedades C ++ e ponteiros de instância de classe, na forma de caminho, e com base nessas informações, você pode gerar xml, json ou até serializar aquele pela Internet.
Exemplos dessas funções virtuais de retorno de chamada podem ser encontrados aqui:
https://github.com/tapika/cppscriptcore/blob/master/SolutionProjectModel/VCConfiguration.cpp
Veja funções
ReflectCopy
e função virtual::OnAfterSetProperty
.Mas como o tópico é realmente avançado - recomendo verificar primeiro o vídeo.
Se você tiver algumas idéias de melhoria, não hesite em entrar em contato comigo.
fonte
A reflexão em C ++ é muito útil, nos casos em que você precisa executar algum método para cada membro (por exemplo: serialização, hash, comparação). Eu vim com solução genérica, com sintaxe muito simples:
Onde ENUMERATE_MEMBERS é uma macro, descrita mais adiante (UPDATE):
Suponha que definimos a função de serialização para int e std :: string assim:
E nós temos uma função genérica perto da "macro secreta";)
Agora você pode escrever
Portanto, com a macro ENUMERATE_MEMBERS na definição da estrutura, é possível criar serialização, comparação, hash e outros itens sem tocar no tipo original, o único requisito é implementar o método "EnumerateWith" para cada tipo, que não é enumerável, por enumerador (como BinaryWriter) . Normalmente, você precisará implementar de 10 a 20 tipos "simples" para oferecer suporte a qualquer tipo no seu projeto.
Essa macro deve ter zero de sobrecarga para estruturar a criação / destruição em tempo de execução, e o código de T.EnumerateWith () deve ser gerado sob demanda, o que pode ser alcançado com a função de linha de modelo, portanto, a única sobrecarga em toda a história é adicionar ENUMERATE_MEMBERS (m1, m2, m3 ...) a cada estrutura, enquanto a implementação de métodos específicos por tipo de membro é uma obrigação em qualquer solução, por isso não assumo isso como sobrecarga.
UPDATE: Existe uma implementação muito simples da macro ENUMERATE_MEMBERS (no entanto, pode ser um pouco estendido para suportar a herança de estruturas enumeráveis)
E você não precisa de nenhuma biblioteca de terceiros para essas 15 linhas de código;)
fonte
Você pode obter recursos interessantes de reflexão estática para estruturas com o BOOST_HANA_DEFINE_STRUCT da biblioteca Boost :: Hana.
Hana é bastante versátil, não apenas para o caso de uso que você tem em mente, mas também para muita metaprogramação de modelos.
fonte
A reflexão de acesso aleatório biblioteca permite uma reflexão bastante fácil e intuitiva - todas as informações de campo / tipo são projetadas para estarem disponíveis em matrizes ou parecerem com acesso a matrizes. Ele foi escrito para C ++ 17 e funciona com Visual Studios, g ++ e Clang. A biblioteca é apenas de cabeçalho, o que significa que você só precisa copiar "Reflect.h" no seu projeto para usá-lo.
Estruturas ou classes refletidas precisam da macro REFLECT, onde você fornece o nome da classe que está refletindo e os nomes dos campos.
Isso é tudo o que existe, nenhum código adicional é necessário para configurar a reflexão. Opcionalmente, você pode fornecer superclasses (entre parênteses do primeiro argumento) e anotações de campo (entre parênteses anteriores ao campo que deseja anotar) para poder atravessar superclasses ou adicionar informações adicionais em tempo de compilação a um campo (como Json: :Ignorar).
Dar laços nos campos pode ser tão simples quanto ...
Você pode percorrer uma instância do objeto para acessar valores de campo (que você pode ler ou modificar) e informações de tipo de campo ...
Uma biblioteca JSON é construída sobre RandomAccessReflection, que identifica automaticamente representações de saída JSON apropriadas para leitura ou gravação e pode percorrer recursivamente qualquer campo refletido, bem como matrizes e contêineres STL.
O acima pode ser executado assim ...
Veja também...
fonte
Se você declarar um ponteiro para uma função como esta:
Você pode atribuir um lugar na memória a essa função como esta (requer
libdl
edlopen
)Para carregar um símbolo local usando indiretamente, você pode usar
dlopen
o binário chamador (argv[0]
).O único requisito para isso (além de
dlopen()
,libdl
edlfcn.h
) é conhecer os argumentos e o tipo da função.fonte