在c ++中检查运行时的可转换性

mg8*_*g84 4 c++ type-conversion

在c ++中,隐式地完成了不同类型的转换.例如,int可以将类型的对象分配给const int(如下面代码中主函数的第一行中所做的那样).

现在我想检查运行时的可转换性,因为我有一个可以添加类型的结构,后来我想检查给定类型,如果结构中存储的类型之一可以转换为给定类型.

这是我到目前为止提出的:

#include <iostream>
#include <vector>

struct bar { virtual void dummy() {} };
template<typename T> struct foo : public bar { virtual void dummy() {} };

int main() {

    int i1 = 1;
    const int i2 = i1;

    std::vector<bar*> bars;
    bar* t1 = new foo<int>; bars.push_back(t1);
    bar* t2 = new foo<int const>; bars.push_back(t2);

    foo<int const>* t3 = dynamic_cast<foo<int const>*>(bars[0]);
    std::cout << t3 << std::endl;

    foo<int const>* t4 = dynamic_cast<foo<int const>*>(bars[1]);
    std::cout << t4 << std::endl;

    delete t1;
    delete t2;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

为了在结构中存储类型,我创建了foo源自的模板化结构bar.然后我可以存储不同类型的intint const(准确地说指针类型的对象foo<int>foo<int const>)中的一个向量bar*秒.然后对于给定类型(这里int const)我检查此向量中的每个元素是否可以动态地转换为foo具有此类型的元素.

当运行该代码t3将成为nullptrt4非空指针.但我想要t3一个非空指针.

我希望它变得非常清楚我想做什么.

您是否有任何想法如何在运行时实现这种可转换性检查(涉及c ++ 11功能的解决方案完全没问题)?

Moo*_*uck 6

不幸的是,既然foo<int>并且foo<const int>是完全不相关的类型,你就不能轻易做到这一点.

bar* t1 = new foo<int>;
foo<int const>* t3 = ?????<foo<int const>*>(t1);
Run Code Online (Sandbox Code Playgroud)

t3不能以任何部分的指针t1,由于t1两者都不是,也不包含,一个foo<int const>用于t3向点.获得任何良好行为的唯一方法是制作一个全新的数据副本.这种令人沮丧的限制是模板可以与不相关的类型进行特殊化的副作用,这是一个非常强大的工具,但却导致了这种混乱.一般的经验法则是不要将const/volatile资格,也不要将任何类型的引用放入模板参数中,除非这是模板类的唯一原因(例如).t1foo<int const>*std::remove_reference

然而,我才意识到,你想要的是foo<int>foo<const int>是同一类型(ISH),并且可以做到(sortof)!

struct base { 
    virtual ~base(){}; //always have virtual destructor with polymorphism
    virtual void dummy()=0; //pure virtual, forces override
};
template<typename T> 
struct foo : public bar { 
    virtual void dummy() {} 
};
template<typename T> struct foo<const T> : public foo<T> {};
template<typename T> struct foo<volatile T> : public foo<T> {};
template<typename T> struct foo<const volatile T> : public foo<T> {};


base* t1 = new derived<const int>;
derived<int>* t3 = dynamic_cast<derived<int>*>(t1); //hooray!
//you can go from derived<const int> to derived<int> but not the other way around
Run Code Online (Sandbox Code Playgroud)