Obtenez constexpr sans exécuter le programme
J'ai une bibliothèque (à la fois comme source et compilée) et j'écris un programme (non lié à cette bibliothèque) qui a besoin de savoir si un type de la bibliothèque est par exemple trivialement copiable ou non.
Je pourrais faire en sorte que mon programme écrive ce qui suit dans 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';
}
puis compilez et exécutez ce code et analysez la sortie. Existe-t-il une meilleure façon d'obtenir ces informations? (la performance est importante). La libclang peut-elle faire ça?
MISE À JOUR à cause des commentaires:
En ce qui concerne le problème XY: ce que j'essaie de faire, c'est d'écrire un programme (appelé rust-bindgen) dans rust, qui obtient le chemin d'un fichier d'en-tête C ++ en tant qu'argument am et génère des liaisons rust-c ++ pour ce fichier d'en-tête. J'ai besoin de générer les liaisons différemment selon que le type est trivialement copiable / relocalisable.
J'ai donc un chemin vers un fichier d'en-tête C ++ et j'ai besoin de savoir si un type donné défini dans ce fichier d'en-tête est facilement copiable. L'approche ci-dessus fonctionne, mais est lente, car elle implique la compilation de file.cpp.
TLDR: Comment puis-je écrire une fonction de rusticité rapide, qui prend deux chaînes comme argument et renvoie un booléen: La première chaîne est le chemin vers un fichier d'en-tête C ++, la deuxième chaîne est le nom d'un type défini dans ledit fichier d'en-tête. Il doit renvoyer un booléen indiquant si le type est copiable ou non.
Réponses
Vous allez avoir besoin de compiler le code, au moins en IR. En effet, la trivialité d'une classe C ++ peut dépendre d'un calcul arbitrairement compliqué dont les entrées peuvent inclure des attributs de plate-forme, des en-têtes disponibles, des définitions de préprocesseur, des options de compilateur etc., qui ne peuvent donc être effectués que par un compilateur C ++.
Si vous invoquez clang en tant que binaire, l'option pour émettre IR est clang -S -emit-llvm
et vous voudrez alors analyser la sortie LLVM IR; par exemple pour
#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;
l'IR est:
@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
Si vous souhaitez utiliser libclang, vous devrez invoquer EmitLLVMOnlyAction en donnant un module dont vous pourrez ensuite extraire les définitions GlobalVariable. Voir: Méthode pour créer LLVM IR