Pobierz constexpr bez uruchamiania programu
Mam bibliotekę (zarówno jako źródłową, jak i skompilowaną) i piszę program (niepowiązany z tą biblioteką), który musi wiedzieć, czy jakiś typ w bibliotece jest np. Trywialnie kopiowalny, czy nie.
Mogę sprawić, by mój program zapisał w pliku 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';
}
następnie skompiluj i uruchom ten kod i przeanalizuj dane wyjściowe. Czy jest lepszy sposób na uzyskanie tych informacji? (wydajność jest ważna). Czy libclang może to zrobić?
UPDATE z powodu komentarzy:
Odnośnie problemu XY: To, co próbuję zrobić, to napisać program (o nazwie rust-bindgen) w rdzeniu, który pobiera ścieżkę pliku nagłówkowego C ++ jako argument am i generuje powiązania rust-c ++ dla tego pliku nagłówkowego. Muszę generować powiązania inaczej w zależności od tego, czy typ jest trywialnie kopiowalny / relokowalny.
Mam więc ścieżkę do pliku nagłówkowego C ++ i muszę wiedzieć, czy dany typ zdefiniowany w tym pliku nagłówkowym można w prosty sposób skopiować. Powyższe podejście działa, ale jest powolne, ponieważ wymaga kompilacji pliku.cpp.
TLDR: Jak mogę napisać funkcję szybkiej rdzy, która przyjmuje dwa ciągi jako argument i zwraca wartość bool: pierwszy ciąg to ścieżka do pliku nagłówkowego C ++, drugi ciąg to nazwa typu zdefiniowanego we wspomnianym pliku nagłówkowym. Powinien zwrócić wartość bool, która mówi, czy typ można w prosty sposób skopiować, czy nie.
Odpowiedzi
Będziesz musiał skompilować kod, przynajmniej do IR. Dzieje się tak, ponieważ trywialność klasy C ++ może zależeć od arbitralnie skomplikowanych obliczeń, których dane wejściowe mogą obejmować atrybuty platformy, dostępne nagłówki, definicje preprocesora, opcje kompilatora itp., Które mogą być zatem wykonywane tylko przez kompilator C ++.
Jeśli wywołujesz clang jako plik binarny, opcja emitowania IR jest, clang -S -emit-llvm
a wtedy będziesz chciał przeanalizować wyjście LLVM IR; na przykład dla
#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;
IR to:
@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
Jeśli chcesz użyć libclang, będziesz musiał wywołać EmitLLVMOnlyAction, podając moduł, z którego możesz następnie wyodrębnić definicje GlobalVariable. Zobacz: Metoda tworzenia LLVM IR