Как сделать dynamic_cast указатель класса без виртуального метода? - PullRequest
0 голосов
/ 07 июня 2018

Я использую библиотеку llvm и хочу проверить, является ли llvm :: Value * на самом деле llvm :: LoadInst * (llvm :: LoadInst наследуется от llvm :: Value).

Но, к сожалению, llvm :: Value не содержит виртуальных методов!(Да, даже без виртуального деструктора) Можно ли использовать dynamic_cast в классе без виртуальных методов или есть какой-либо другой способ проверки типов?

Ответы [ 2 ]

0 голосов
/ 07 июня 2018

Можно ли использовать dynamic_cast в классе без виртуальных методов,

Невозможно использовать dynamic_cast, если вход не является указателем или ссылкой на полиморфныйтипа, т.е. не имеет virtual функций-членов.

или есть какой-либо другой способ сделать проверку типа?

Я не могу придумать ни одного,Лучше всего использовать static_cast, но тогда вы должны быть уверены, что тип, к которому вы ведете, действителен.

struct Base { ... };
struct Derived1 : Base { ... };
struct Derived2 : Base { ... };

void foo(Base* base)
{
    Derived1* ptr = static_cast<Derived1*>(base);
    // Use ptr
}

void bar()
{
    foo(new Derived1()); // OK.
    foo(new Derived2()); // Not OK since foo assumes that the pointer 
                         // really points to a Derived1 object.
}
0 голосов
/ 07 июня 2018

В LLVM есть llvm::dyn_cast<T>, который будет использовать внутренние конструкции LLVM для динамического приведения из одного типа в другой, если они действительно являются допустимыми приведениями - если вы используете неправильный тип T, он вернетnullptr.

Так что-то вроде:

llvm::Value *v = ... some code here ... 
...
llvm::LoadInst* li = llvm::dyn_cast<llvm::LoadInst>(v);
if (!li) { ... not a LoadInst, do whatever you should do here ... }
else { ... use li ... }

Естественно, если вы уже ДЕЙСТВИТЕЛЬНО знаете, что v - это LoadInst, вам не нужно проверять - ноassert(li && "Expected a LoadInst"); поймает, если вы когда-нибудь ошиблись.

Обратите внимание, что вы не используете T* для llvm::dyn_cast<T>, как вы бы использовали для стандарта C +++ dynamic_cast.

Этот комментарий в коде для llvm::Value объясняет, что по этой причине не существует vtable (http://www.llvm.org/doxygen/Value_8h_source.html#l00207)

   /// Value's destructor should be virtual by design, but that would require
   /// that Value and all of its subclasses have a vtable that effectively
   /// duplicates the information in the value ID. As a size optimization, the
   /// destructor has been protected, and the caller should manually call
   /// deleteValue.
   ~Value(); // Use deleteValue() to delete a generic Value.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...