检查强制转换FROM shared_ptr <void> </void>

时间:2014-11-26 19:50:54

标签: c++ c++11 casting shared-ptr smart-pointers

我试图从shared_ptr<void>施放。我知道它是shared_ptr<A>shared_ptr<B>,但我找不到如何检查它是哪一个。 A和B是2个不相关的类。

我想做点什么:

//x.valuePtr is a shared_ptr<void>
if(x.valuePtr is shared_ptr<A>){
  ... do things with the pointer to an A object
} else if (x.valuePtr is shared_ptr<B>){
  ... do things with the pointer to an B object
}

我有一个属性(我无法更改的类),类型为shared_ptr<void>。  在大多数情况下,我知道哪个是指针的真实类型,所以我可以毫无问题地使用static_pointer_cast。例如:

// If I know x.valuePtr is shared_ptr<A>
x.valuePtr = std::make_shared<A>();

// I can use static_pointer_cast somewhere else in the application and it works fine
std::shared_ptr<A> a_ptr = std::static_pointer_cast<A> (x.valuePtr);

// Same happens when I know it is a shared_ptr<B>
x.valuePtr = std::make_shared<B>();
std::shared_ptr<B> b_ptr = std::static_pointer_cast<B> (x.valuePtr);

但现在我遇到了问题,因为它可能是其中之一(shared_ptr<A>shared_ptr<B>)。如果我使用static_pointer_cast<A>(或<B>),该行编译并抛出没有异常,但是一旦我尝试使用来自casted ptr的特定内容(如果它是错误的类型)它会抛出异常。例如:

  // If x.valuePtr is shared_ptr<A>
  x.valuePtr = std::make_shared<A>();

  // But if I try to cast it to shared_ptr<B> somewhere in the application where it could be shared_ptr<A> or shared_ptr<B>
  std::shared_ptr<B> b_ptr = std::static_pointer_cast<B> (x.valuePtr); // this does no fail

  // It throws an exception when I try to use b_ptr. For example
  b_ptr->AMethodInB();

我尝试在static_pointer_cast之后进行不同的检查(对于null,空shared_ptr等),但似乎没有任何效果:

x.valuePtr = std::make_shared<A>();
std::shared_ptr<B> b_ptr = std::static_pointer_cast<B> (x.valuePtr); 
if(b_ptr == NULL || b_ptr.get() == NULL || !b_ptr){
   "It never gets into this line"
   "I would be able to try to cast it to shared_ptr<A>"
}

 b_ptr->AMethodInB(); // and keeps failing here

我也尝试使用dynamic_pointer_cast<B>,但没有编译(&#34; error: cannot dynamic_cast .... (source is not a pointer to class)&#34;)。另外,我发现无法dynamic_cast FROM void here

我有什么方法可以检查static_pointer_cast是否真的有效? 或者以某种方式检查此shared_ptr<void>的实际类型?

PD:我使用的是c ++ 11,gcc 4.8.2。

2 个答案:

答案 0 :(得分:0)

如果您需要提供类型信息,我对使用std::shared_ptr<void>感到奇怪。

可能最好使用基于模板的方法(某种名称是类型特征)?

struct A
{
    int id;
};

struct B
{
    int id1;
};

//Default template (neither A or B)
template<typename T>
struct Checker
{
    enum { isA = 0, isB = 0 };
};

//Template for A
template<>
struct Checker<A>
{
    enum { isA = 1, isB = 0 };
};

//Template for B
template<>
struct Checker<B>
{
    enum { isA = 0, isB = 1 };
};

//Convenience function (only thing it does in runtime is compare 2 ints)
template<typename T>
bool checkA(std::shared_ptr<T> p)
{
    return Checker<T>::isA == 1;
}

//Convenience function (only thing it does in runtime is compare 2 ints)
template<typename T>
bool checkB(std::shared_ptr<T> p)
{
    return Checker<T>::isB == 1;
}

//Convenience function
template<typename T>
void test(std::shared_ptr<T> p)
{
    std::cout
        << "is A : " << checkA(p)
        << " is B : " << checkB(p) << std::endl;
}

void test()
{
    //This is working
    std::shared_ptr<A> a = std::make_shared<A>();
    std::shared_ptr<B> b = std::make_shared<B>();
    test(a);
    test(b);

    //This is not working
    std::shared_ptr<void> a1 = std::make_shared<A>();
    std::shared_ptr<void> b1 = std::make_shared<B>();
    test(a1);
    test(b1);
}

输出结果为:

is A : 1 is B : 0
is A : 0 is B : 1
is A : 0 is B : 0
is A : 0 is B : 0

答案 1 :(得分:0)

您应该为BaseA创建公共基类(B)。然后可以将shared_ptr<void>转换为shared_ptr<Base>,将static_pointer_cast<Base>(...)dynamic_pointer_cast结果转换为AB

通过向do_things添加纯虚拟成员函数Base并在AB中使用{... do things with the pointer to an A object覆盖它,可能会更好地避免动态强制转换。 1}}和... do things with the pointer to a B object