Ottieni constexpr senza eseguire il programma
Ho una libreria (sia come sorgente che come compilata) e sto scrivendo un programma (non collegato a questa libreria) che ha bisogno di sapere se qualche tipo nella libreria è, ad esempio, banalmente copiabile o meno.
Potrei fare in modo che il mio programma scriva quanto segue in 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';
}
quindi compilare ed eseguire questo codice e analizzare l'output. C'è un modo migliore per ottenere queste informazioni? (le prestazioni sono importanti). Può libclang farlo?
AGGIORNAMENTO a causa di commenti:
Per quanto riguarda il problema XY: Quello che sto cercando di fare è scrivere un programma (chiamato rust-bindgen) in rust, che ottiene il percorso di un file di intestazione C ++ come argomento am e genera i collegamenti rust-c ++ per quel file di intestazione. Ho bisogno di generare le associazioni in modo diverso a seconda che il tipo sia banalmente copiabile / rilocabile.
Quindi ho un percorso per un file di intestazione C ++ e ho bisogno di sapere se un dato tipo definito in quel file di intestazione è banalmente copibile. L'approccio sopra funziona, ma è lento, perché implica la compilazione di file.cpp.
TLDR: Come posso scrivere una funzione ruggine veloce, che accetta due stringhe come argomento e restituisce un bool: La prima stringa è il percorso di un file di intestazione C ++, la seconda stringa è il nome di un tipo definito in detto file di intestazione. Dovrebbe restituire un bool che dice se il tipo è banalmente copibile o meno.
Risposte
Avrai bisogno di compilare il codice, almeno su IR. Questo perché la banalità di una classe C ++ può dipendere da un calcolo arbitrariamente complicato i cui input possono includere attributi della piattaforma, intestazioni disponibili, definizioni del preprocessore, opzioni del compilatore ecc., Che possono quindi essere eseguiti solo da un compilatore C ++.
Se stai invocando clang come binario, l'opzione per emettere IR è clang -S -emit-llvme allora vorrai analizzare l'output IR di LLVM; per esempio per
#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;
il loro è:
@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 vuoi usare libclang, dovrai invocare EmitLLVMOnlyAction fornendo un modulo da cui puoi estrarre le definizioni GlobalVariable. Vedi: Metodo per creare LLVM IR