2017-10-01 8 views
0
struct A 
{ 
}; 
struct B : A 
{ 
    virtual ~B() {} 
}; 
template<typename BASE, typename EXTENDED> 
void ASSERT_BASE_EXTENDED() 
{ 
    static_assert(static_cast<BASE*>((EXTENDED*)256)==(BASE*)256, "error"); 
} 

Je suis à la recherche d'un moyen d'avoir une affirmation de compilation pour vérifier si la classe de base est une base de PROLONGÉE, et ils ont le même adresse mémoire. Dans l'exemple ci-dessus, même si B est basé sur A, lorsqu'il est converti en A, il a une adresse de mémoire différente, car le pointeur de table de fonction virtuelle est en fait le premier membre de B. Mais j'ai besoin de vérifier premier membre Ce qui précède fonctionne bien mais n'est pas à la compilation, car j'obtiens une erreur "erreur C2131: l'expression n'a pas été évaluée comme une constante" lors de l'utilisation du compilateur VS 2017.C++ compilation assert cette base est la classe de base de ETENDU et ont la même adresse mémoire

Je ne m'intéresse pas à "std :: is_base_of" parce que celui-ci ignore la vérification de la même adresse mémoire. Existe-t-il un autre moyen de le faire?

Merci

+0

Vous voulez utiliser le [_CRTP_] (https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern) et 'static_cast'? – user0042

+0

Le CRTP est un concept intéressant mais l'objectif est de ne pas modifier les classes existantes et d'ajuster uniquement la fonction ASSERT_BASE_EXTENDED. – Esenthel

Répondre

1

Les adresses de mémoire sont une construction d'exécution. Vous ne pouvez pas les vérifier au moment de la compilation, car à ce stade, ils n'existent pas. La même chose est vraie pour le genre de casting que vous mentionnez. Cela arrive à l'exécution entièrement. Vous devrez remplacer static_assert par une vérification de l'exécution et une gestion des erreurs, par ex. assert() ou une exception.

C'est pour le cas d'utilisation commun d'imo. Pour les adresses de mémoire codées en dur comme dans votre exemple, le problème est la distribution de ces adresses aux pointeurs. La seule façon valide de le faire est un reinterpret_cast (c'est l'un des moulages que le compilateur essaie pour le cast de style C dans votre exemple), car les types int et pointent sur T sont complètement indépendants. Mais reinterpret_cast n'est pas autorisé au moment de la compilation.

message d'erreur de Clang met bien:

main.cpp:14:38: note: cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression 
    static_assert(static_cast<BASE*>((EXTENDED*)256)==(BASE*)256, "error"); 
            ^
+0

Je ne suis pas d'accord avec vous. Si vous vérifiez à nouveau mon code, vous verrez que je crée un pointeur vers un objet à partir d'une adresse mémoire constante de 256. Aussi, j'utilise static_cast qui contrairement à dynamic_cast peut effectuer des ajustements au décalage de mémoire par une valeur connue du compilateur . Rien n'empêche le compilateur d'évaluer la ligne entière au moment de la compilation, mais ce n'est pas le cas. Ce sont essentiellement des opérations arithmétiques sur des constantes connues au moment de la compilation. – Esenthel

+0

J'ai intuitivement pris ces adresses codées en dur pour simplifier les questions. Pour ce cas, le problème réel sont les moulages. Voir la réponse mise à jour. – besc

+0

IMO tout ce que les compilateurs pourraient optimiser (pré-calcul) - ils devraient. Si tel était le cas, cela résoudrait mon problème. – Esenthel