不同返回类型的方法的类型擦除

4
我想知道是否存在某种类型抹消机制来处理具有相同名称和参数但返回不同值的方法,就像下面的示例中的beginend。 我没有计划在任何地方实际使用它,我只是想知道是否可能,如果可能,如何完成。
我所知道的唯一类型抹消形式是拥有指向纯虚拟concept类的指针,该指针指向转发调用到基础Tmodel<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 << ' ';
    }
}
3个回答

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();
   }
};

请注意,这个模式与常规的多态层次结构非常相似,不同之处在于添加了一个“接口”对象,它是一个值类型(从C#借用术语“值类型”),它包含实际的多态对象。
从这个角度看,它似乎有点简单和无用,但这是推动boost :: any(内部接口仅为typeid),std :: function (内部接口是它实现void operator()),或shared_ptr <>(接口是放弃资源的删除器方法)的燃料。
当需要做的唯一事情是销毁实现类型擦除的类型时,存在一种特定类型不同的类型擦除:使用临时变量并将其绑定到常量引用...但这非常具体,如果您想了解更多信息,请阅读此处:http://drdobbs.com/cpp/184403758 在问题中谈论的特定情况中,它更加复杂,因为您不想抹掉单个类型,而是要抹掉几个类型。Iterable接口必须抹掉它内部持有的容器的类型,并在此过程中提供自己的迭代器,这些迭代器必须对容器的迭代器执行类型擦除。尽管如此,基本思想仍然是相同的,只是需要更多的工作来实现。

1

仅提供链接的答案在未来会出现“位腐烂”问题,您能否加入一些内容来扩充一下呢? - TemplateRex

0

C++标准库不支持在其容器类型中进行运行时差异。实现这一点没有问题,但是在语言级别没有垃圾回收的情况下进行内存管理将会非常困难,你需要花费很多精力来使其高效。

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

此外,你需要非常小心。向量肯定是RandomAccessIterable,但集合只是ConstIterable,绝对不是RandomAccessIterable,而InputIterator只是ForwardIterable。你需要为所有这些情况定义模板。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接