4

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

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

到目前为止,这是我想出的:

#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. 然后我可以将不同的类型intint const(精确地指向类型foo<int>和的对象的指针foo<int const>)存储在 s 的向量中bar*。然后对于给定的类型(此处int const),我检查此向量中的每个元素是否可以动态转换为foo具有此类型的 a。

运行此代码时,t3将变为非空指针。但我也想拥有一个非空指针。nullptrt4t3

我希望我想做什么变得大致清楚。

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

4

2 回答 2

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>for 。t3从中获得任何良好行为的唯一方法是将保存的数据复制t1到一个全新的foo<int const>*. 这个令人沮丧的限制是模板可专门用于不相关类型的副作用,这是一个非常强大的工具,但会导致这种混乱。一般的经验法则是不要将 const/volatile 限定条件或任何类型的引用放入模板参数中,除非这是模板类的唯一原因(例如std::remove_reference)。

但是,我刚刚意识到,您想要的是 forfoo<int>和 forfoo<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
于 2013-06-28T21:16:47.010 回答
-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例如关于 ness 的例外行为。

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

于 2013-06-28T21:19:39.007 回答