Obtenha constexpr sem executar o programa
Eu tenho uma biblioteca (como fonte e compilada) e estou escrevendo um programa (não vinculado a esta biblioteca) que precisa saber se algum tipo na biblioteca, por exemplo, pode ser copiado facilmente ou não.
Eu poderia fazer meu programa escrever o seguinte em file.cpp:
#include "mylibrary.hpp"
int main()
{
std::cout << std::is_trivially_copyable<A>::value << '\n';
std::cout << std::is_trivially_copyable<B>::value << '\n';
std::cout << std::is_trivially_copyable<C>::value << '\n';
std::cout << std::is_trivially_copyable<D>::value << '\n';
}
em seguida, compile e execute esse código e analise a saída. Existe uma maneira melhor de obter essas informações? (o desempenho é importante). A libclang pode fazer isso?
ATUALIZAR devido a comentários:
Com relação ao problema XY: O que estou tentando fazer é escrever um programa (chamado rust-bindgen) em rust, que obtém o caminho de um arquivo de cabeçalho C ++ como um argumento e gera ligações rust-c ++ para esse arquivo de cabeçalho. Preciso gerar as ligações de maneira diferente, dependendo se o tipo é trivialmente copiável / relocável.
Portanto, tenho um caminho para um arquivo de cabeçalho C ++ e preciso saber se um determinado tipo definido nesse arquivo de cabeçalho pode ser copiado de maneira trivial. A abordagem acima funciona, mas é lenta, porque envolve a compilação de file.cpp.
TLDR: Como posso escrever uma função de ferrugem rápida, que recebe duas strings como argumento e retorna um bool: A primeira string é o caminho para um arquivo de cabeçalho C ++, a segunda string é o nome de um tipo definido no referido arquivo de cabeçalho. Ele deve retornar um bool que diz se o tipo é trivialmente copiável ou não.
Respostas
Você vai precisar compilar o código, pelo menos para IR. Isso ocorre porque a trivialidade de uma classe C ++ pode depender de uma computação arbitrariamente complicada cujas entradas podem incluir atributos de plataforma, cabeçalhos disponíveis, definições de pré-processador, opções de compilador etc., que, portanto, só podem ser realizadas por um compilador C ++.
Se você estiver chamando o clang como um binário, a opção de emitir IR é clang -S -emit-llvm
e você desejará analisar a saída IR do LLVM; por exemplo para
#include <type_traits>
struct A {};
struct B { B(B const&); };
struct C { ~C(); };
struct D { D(D const&) = default; };
int a = std::is_trivially_copyable<A>::value;
int b = std::is_trivially_copyable<B>::value;
int c = std::is_trivially_copyable<C>::value;
int d = std::is_trivially_copyable<D>::value;
o IR é:
@a = dso_local local_unnamed_addr global i32 1, align 4, !dbg !0
@b = dso_local local_unnamed_addr global i32 0, align 4, !dbg !6
@c = dso_local local_unnamed_addr global i32 0, align 4, !dbg !10
@d = dso_local local_unnamed_addr global i32 1, align 4, !dbg !12
^ variable name ^ initializer
Se você quiser usar libclang, você precisará invocar EmitLLVMOnlyAction fornecendo um Módulo do qual você pode extrair as definições GlobalVariable. Veja: Método para criar LLVM IR