与模板成员函数

时间:2016-05-15 09:40:01

标签: c++ oop templates functional-programming

我有兴趣为C ++实现类似Java集合的环境。 我知道这不是一个好主意等等,但我不想在以后使用它,但只是学习如何做一些高级OOP。

我的问题是我想要一个带有纯虚函数的基类模板collection<T>。其中一个函数应为map(),其中std::function<R(T)>map()。由于collection<R>应该是虚拟的,我不知道我应该使用哪种返回类型。 map()是不可能的,因为成员函数模板不能是虚拟的。

如何为collection<T>界面添加此类strategy: type: "Docker" dockerStrategy: noCache: true 成员函数?

2 个答案:

答案 0 :(得分:7)

  

如何为map界面添加此类collection<T>成员函数?

简短的回答是:你不是。如果我有一些collection<int>并且我想map std::to_string,我需要生成一个collection<std::string>。但vector_collection<int>需要生成vector_collection<std::string>list_collection<int>需要生成list_collection<std::string> - 因此类型转换本身需要virtual。但是你不能拥有virtual个成员函数模板,因此无法表达这一点。

为了实现这一点,您必须为您放入容器中的所有对象设置一个公共基本类型,然后才能拥有一个可以在其间投射的公共外观。也就是说,您实际上只有collection<unique_ptr<Object>> map只是为您提供了不同的collection<unique_ptr<Object>>,而您只是mapcollection_facade<int, collection<unique_ptr<Object>>>改为collection_facade<std::string, collection<unique_ptr<Object>>> 。通过大量工作并完全无视性能和类型安全性,您可以实现目标。

这是模板的优势。如果我想为map之类的内容写vector,我可以写下:

template <class T, class A, class F, class R = std::result_of_t<F(T)>>
std::vector<R, A> map(std::vector<T, A> const& v, F f) {
    std::vector<R, A> mapped;
    mapped.reserve(v.size());
    for (T const& elem : v) {
        mapped.push_back(f(elem));
    }
    return mapped;
}

或:

template <class T, class A, class F, class R = std::result_of_t<F(T)>>
std::vector<R, A> map(std::vector<T, A> const& v, F f) {
    return std::vector<R, A>(
        boost::make_transform_iterator(v.begin(), f),
        boost::make_transform_iterator(v.end(), f)
        );
}

我必须分别为每个容器实现map() - 但无论如何我都必须这样做。而现在我没有放弃任何东西。此外,您经常编写与运行时容器无关的算法吗?

答案 1 :(得分:0)

实施map作为外部模板功能。 例如,您可以分两个阶段分解map,内部虚拟生产者和外部模板化消费者。

template<typename T> struct Collection {
    // virtual T next(); // Java way
    // C++ way
    // In simplest cases you can rely on iterator pairs.
    struct const_iterator {
        T const &operator*() const;
        const_iterator &operator++();
    }
    virtual const_iterator begin() const;
    virtual const_iterator end() const;
};
template<typename R, typename T> Collection<R> map(
    Collection<T> const &coll, std::function<R(T)> const &f);

要实现本质上复杂的容器和monadic组合,您甚至可以拒绝begin()end()并编写显式(部分)模板专业化。