Dapatkan constexpr tanpa menjalankan program
Saya memiliki perpustakaan (baik sebagai sumber maupun yang dikompilasi) dan saya sedang menulis program (tidak terkait dengan perpustakaan ini) yang perlu mengetahui apakah beberapa jenis di perpustakaan misalnya dapat disalin secara sepele atau tidak.
Saya bisa membuat program saya menulis berikut ini ke 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';
}
kemudian kompilasi dan jalankan kode ini dan parse hasilnya. Adakah cara yang lebih baik untuk mendapatkan informasi ini? (kinerja itu penting). Bisakah libclang melakukan itu?
UPDATE karena komentar:
Mengenai masalah XY: Yang saya coba lakukan, adalah menulis program (disebut rust-bindgen) di rust, yang mendapatkan jalur file header C ++ sebagai argumen saya dan menghasilkan binding rust-c ++ untuk file header itu. Saya perlu menghasilkan binding secara berbeda tergantung pada apakah jenisnya dapat disalin / direlokasi secara sepele.
Jadi saya memiliki jalur ke file header C ++ dan saya perlu tahu apakah tipe tertentu yang ditentukan dalam file header itu dapat disalin dengan mudah. Pendekatan di atas berfungsi, tetapi lambat, karena melibatkan kompilasi file.cpp.
TLDR: Bagaimana saya bisa menulis fungsi karat cepat, yang mengambil dua string sebagai argumen dan mengembalikan bool: String pertama adalah jalur ke file header C ++, string kedua adalah nama jenis yang ditentukan dalam file header tersebut. Ini harus mengembalikan bool yang mengatakan apakah tipe tersebut dapat disalin dengan mudah atau tidak.
Jawaban
Anda perlu mengkompilasi kode, setidaknya ke IR. Ini karena trivialitas kelas C ++ dapat bergantung pada komputasi rumit sewenang-wenang yang inputnya dapat mencakup atribut platform, header yang tersedia, definisi preprosesor, opsi kompilator, dll., Yang dengan demikian hanya dapat dijalankan oleh kompilator C ++.
Jika Anda menggunakan dentang sebagai biner, opsi untuk memancarkan IR adalah clang -S -emit-llvm
dan Anda kemudian ingin mengurai keluaran LLVM IR; misalnya untuk
#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 adalah:
@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
Jika Anda ingin menggunakan libclang, Anda perlu menjalankan EmitLLVMOnlyAction yang memberikan Modul yang kemudian dapat Anda ekstrak definisi GlobalVariable darinya. Lihat: Metode pembuatan LLVM IR