检查指向基类的指针是否是使用可变参数模板派生的

时间:2018-03-24 07:52:23

标签: c++ templates polymorphism variadic-templates

我有一个多态类型Base,它是许多其他类型的基类:

class Base
{
 Base() {}
 virtual ~Base() {}
};

其中一个派生类包含一个值,该值由类型T模板化。 此类还可以包含指向该类的另一个实例的指针_stub,它可以是另一个类型T,用作该值的替换。 限制是另一种类型必须是可变参数模板指示的受支持类型之一。 所以_stub是T类型或者是SupportedTypes之一。

我想要下面的 getValue 函数,如果_stub为NULL,则返回类型T的_v,否则返回dynamic_cast _stub 到其原始派生类型(让&# 39; s说X),然后把它扔给T. 要求是类型X必须具有T的强制转换操作符。

保证_stub为T或SupportedTypes之一。

template <typename T, typename... SupportedTypes>
class Generic : public Base
{
public:

 Generic(): _v() {}
 virtual ~Generic() {}

 virtual T getValue() {
       if (_stub) {
         // Attempt dynamic_cast on _stub to type T or 
         // any of SupportedTypes until we find its original type X

        // I'm looking for a solution that would look like the following line
         X* p = dynamic_cast<T,SupportedTypes...>(_stub.get());
         assert(p);
         return (T)*p->_v;
       }
       return _v; 
 }

private:
 T _v;
 std::shared_ptr<Base> _stub;
};

最初,我没有SupportedTypes参数包,我会为类型T专门设置getValue()并做一个dynamic_cast链,但这取决于每个类型T,并且每个类似于getValue()的函数都需要这个级联if / else dynamic_cast soup。

我试图尝试使用可变参数模板SupportedTypes,以便我可以提出一个更好的解决方案,其中派生类只需要指示类型_stub可能在一个地方。

有没有人有这个问题的清洁解决方案?

解决方案:

由于@apple apple

的提示,我实际上使用了boost :: variant

1 个答案:

答案 0 :(得分:2)

事实上,这发生在相关的类Generic中并且如果指针为空则可能使用另一个值是无关紧要的。你想要的是一个函数模板,它转换为从Base通过dynamic_cast派生的单一类型到类似派生的一组其他类型之一:

class B;

// The real work:    
template<class T>
T convert(B *b) {return static_cast<T&>(*b);}
template<class T,class U,class... Rest>
T convert(B *b) {
  if(U *u=dynamic_cast<U*>(b)) return *u; // converted to T
  return convert<T,Rest...>(b);
}

// Example hierarchy:    
struct B {virtual ~B() {}};
struct X : B {};
struct Y : B {};
struct S : B {                  // convertible from other types
  S() {}
  S(X) {}
  S(Y) {}
};

// Example usage:    
S getS(B *b) {return convert<S,X,Y>(b);}