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

Converting Polymorphic Wrapper of type T to type U?

本文关键字:类型 转换 多态 包装      更新时间:2023-10-16

考虑以下非法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);
    }
};

这是你想要的吗?

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


根据你的更新,我认为这就是你想要做的。

#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是很有用的。