为返回类型不同的方法键入擦除

时间:2011-05-22 17:16:10

标签: c++ c++11 type-erasure

我想知道是否存在某种形式的类型擦除来处理具有相同名称和参数但返回不同值的方法,如下面的示例中所示(beginend)。我并没有计划在任何地方实际使用它,我只是想知道它是否可能,如果是的话,它将如何完成。

我知道的唯一一种类型擦除形式是指向纯虚拟concept类的指针,该类指向model<T>,它将调用转发给基础T。但是,这要求所有T包含具有完全相同签名的方法,而在我的示例中,返回类型不同。据我所知,虚拟模板函数需要做一些我要问的事情,但我可能会遗漏一些东西。

class Iterable
{
    //how would this be defined?
}

int main(int argc, char *argv[])
{
    vector<int> v = {1, 2, 3, 4, 5};
    set<string> s = {"foo", "bar", "baz"};

    Iterable iterable;

    if(argc == 2) iterable = v;
    else iterable = s;


    for(auto val : it)
    { 
        cout << val << ' ';
    }
}

4 个答案:

答案 0 :(得分:10)

类型擦除可以并且已经在不同的上下文中用C ++实现。 boost::anystd::function< signature >std::thread和其他方法中使用的最常见方法基于非多态类,即类型已擦除对象,其中包含指向接口类型的指针。在内部,在构造,分配期间或在擦除用户类型时,实例化并存储接口的实现。

作为一个激励性的简化示例,请考虑我们要创建一个printable类型,可以使用类型擦除来打印任何实现operator<<std::cout的类型。为此,我们需要类型printable,内部接口printable_impl_base和实际实现:

// regular polymorphic hierarchy:
struct printable_impl_base {
   virtual ~printable_impl_base() {}
   virtual void print() const = 0;
};
template <typename T>
struct printable_impl : printable_impl_base {
   T copy_to_print;
   printable_impl( T const & o ) : copy_to_print( o ) {}
   virtual void print() const {
      std::cout << copy_to_print << std::endl;
   }
};

// type erasure is performed in printable:
class printable {
   std::shared_ptr<printablable_impl_base> p;
public:
   template <typename T>
   printable( T obj ) : p( new printable_impl<T>(obj) ) {}
   void print() const {
      p->print();
   }
};

请注意,该模式与常规多态层次结构非常相似,区别在于添加了 interface 对象,这是一种值类型(借用术语值类型来自C#),它保存了实际的多态对象。

以这种方式看待它,似乎有点简单和无用,但这是驱动boost::any的燃料(内部接口只是一个typeid),std::function< void () >(内部接口是那个它实现void operator())或shared_ptr<>(接口是删除方法,放弃资源)。

当实现类型擦除的类型需要完成的唯一事情是销毁它时,有一种特定的不同类型的擦除:使用临时并将其绑定到常量引用...但这是非常的具体,如果您愿意,可以在此处阅读:http://drdobbs.com/cpp/184403758

在您在问题中讨论的特定情况中,它有点复杂,因为您不想删除单个类型,而是删除其中的几个类型。 Iterable接口必须擦除它内部容纳的容器的类型,并且这样做必须提供它自己的迭代器,它必须在容器的迭代器上执行类型擦除。不过,这个想法基本上是一样的,只需要做更多的工作就可以实现。

答案 1 :(得分:1)

您可能对boost::any

感兴趣

http://www.boost.org/doc/libs/1_46_1/doc/html/any.html

答案 2 :(得分:0)

C ++标准库不支持其容器类型中的运行时差异。实现这一点并没有什么不妥,但是,在语言级别没有垃圾收集的内存管理将是非常有趣的,你将会很有趣,使它具有高性能。

值得一提的是,在某些STL实现中,它们实现了一种称为SCARY迭代的东西,其中vector<int, std::allocator<int>>::iteratorvector<int, mycustomallocator<int>>::iterator的类型相同。

此外,你需要非常小心。向量肯定是RandomAccessIterable,但是一个集合只是ConstIterable而且绝对不是RandomAccessIterable,而InputIterator只是ForwardIterable。您必须为所有这些方案定义模板。

答案 3 :(得分:-2)

每当我看到“类型擦除”一词时,我都会感到不舒服。为什么在强类型语言(或弱类型语言)中你想要擦除类型?

不,你不能这样做。