将类型T的多态包装转换为U型?

时间:2012-12-31 04:52:56

标签: c++ templates types c++11 polymorphism

考虑以下非法C ++ 11代码背后的意图:

struct Base
{
    template<typename U>
    virtual U convert() = 0;
};

template<typename T>
struct Derived : Base
{
    T t;

    template<typename U>
    virtual U convert() { return U(t); }
};

struct Any
{
    Base* b;

    template<typename U>
    operator U() { return b->convert<U>(); }
};

int main()
{
    Any a = ...;
    string s = a; // s = a->b->t if T is convertible to string
                  //    fails otherwise with compile error or runtime exception
                  //                            (either acceptable)
}

有没有办法与合法代码达到相同或相似的效果?

(以上方式是非法的,因为templates may not be ‘virtual’

更新

struct Base
{
    void* p;
    type_info type;
};

template<typename T>
struct Derived : Base
{
    Derived()
    {
         p = &t; // immovable
         type = typeid(T);
    }

    T t;
};

struct Any
{
    Base* b;

    template<typename T = U, typename U>
    operator U()
    {
        if (b->type != typeid(T))
           throw exception();

        T* t = (T*) b->p;

        return U(*t);
    }
};

2 个答案:

答案 0 :(得分:0)

这是你想要的吗?

struct Base
{
  virtual void* convert(const std::type_info&) = 0;
};

template<typename T>
struct Derived : Base
{
  virtual void* convert(const std::type_info& ti)
  { return typeid(T) == ti ? &t : nullptr; }

  T t;
};

struct Any
{
  Base* b;

  template<typename U>
    operator U()
    {
      if (auto p = b->convert(typeid(U)))
        return *static_cast<U*>(p);
      throw std::exception();
    }
};

正如另一个答案所说,很难确切地知道你想要什么,因为你只显示了无效的代码,没有解释你想要实现的目标。

编辑哦,我现在看到你希望它适用于任何可转换类型,而不仅仅是完全匹配......那么不,你不能将type_info转回类型它表示,派生类型需要测试给定的type_info是否对应于其存储类型可转换为的类型。您需要知道正确的类型,并通过演绎明确或隐式地指定以某种方式。如果您想将其转换为其他类型,则可以单独执行此操作:

Any a{ new Derived<int>() };
try {
  char c = a;  // throws
}
catch (...)
{
}
int i = a;        // OK
char c = (int)a;  // OK

答案 1 :(得分:-1)


根据您的更新,我认为这就是您要做的事情。

#include <typeinfo>
#include <exception>
#include <string>

template <typename T>
struct Any{
        T* t;
        Any():t(NULL){}
        Any(const T& _t){
                t=new T(_t);
        }
        template<typename U>
        operator U(){
                if(typeid(T)!=typeid(U) || t==NULL)
                        throw std::exception();
                return *t;
        }
};

int main (){
        Any<std::string> a(std::string("Nothing"));
        std::string b=a;
        return 0;
};

如果这没有帮助,请在文字中解释,而不是代码你要实现的目标。告诉我们为什么要使用这两个额外的类Base和Derived会很有用。