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

时间:2013-06-28 20:10:07

标签: 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;
}

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

运行此代码时,t3成为nullptrt4成为非空指针。但我希望t3也有一个非空指针。

我希望我能清楚地知道自己想做什么。

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

2 个答案:

答案 0 :(得分:6)

不幸的是,由于foo<int>foo<const int>是完全不相关的类型,因此您无法轻松完成此操作。

bar* t1 = new foo<int>;
foo<int const>* t3 = ?????<foo<int const>*>(t1);

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

然而,我刚刚意识到,你想要的是foo<const int>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 是同一类型(ish),可以做(sortof) !

{{1}}

答案 1 :(得分:-1)

使用std::is_convertible<From*, To*>::value

#include<type_traits>
int main(){
    using namespace std;
    cout << std::is_convertible<int const, int>::value << endl; // print true
    cout << std::is_convertible<int const*, int*>::value << endl; // print false
    cout << std::is_convertible<int const, int>::value << endl; // print true
    cout << std::is_convertible<std::string, int>::value << endl; // print false
    cout << std::is_convertible<std::string*, int*>::value << endl; // print false
}

请注意,您必须使用指针类型来获取与const相关的例外行为。

(我想在C ++ 98中你可以用boost::is_convertible做同样的事情。)