创建容器的模板类

时间:2019-03-26 22:11:55

标签: c++ templates

我正在尝试创建一个类作为容器包装器,就像这样

#include <vector>

template <typename T, typename U>
class Test {
    T<U> list;
};

int main() {
  Test<std::vector, int> test;
}

但是这行不通。我知道当我这样使用它会起作用

#include <vector>

template <typename T>
class Test {
    T list;
};

int main() {
  Test<std::vector<int>> test;
}

但是我怎么写我的插入物?

template <typename T>
class Test {
    T list;

public:
    void insert(??? element) {
        ...
    }
};

TIA,Narase

2 个答案:

答案 0 :(得分:3)

  

但是这行不通。

在您的第一个摘录Test中,由于std::vector具有two template parameters, value_type and allocator_type,因此我们必须使用 template在T的声明中指定这些模板参数的存在模板参数如下。 在这里,我使用可变参数一个,然后T<U...>合法 T = std::vector并删除了编译错误。

  

我怎么写我的插入物?

以下代码还显示了Test::insert的实现示例。 自this method can accept both lvalue and rvalue references在C ++ 11起,在这里我将转发引用(Scott Meyers称之为universal reference)应用于它。 通过这种方法,我们不需要在Test::list定义中指定Test::insert的值类型,而将错误的类型传递给Test::insert会导致编译错误。 如果您需要值类型为std::vector,则可以使用成员类型std::vector::value_type

template <template<class...> class T, class ...U>
class Test
{
    T<U...> list;

public:
    template<class ...V>
    void insert(V&& ...element) {
        list.insert(std::forward<V>(element)...);
    }

    typename T<U...>::iterator begin() noexcept {
        return list.begin();
    }

    typename T<U...>::iterator end() noexcept {
        return list.end();
    }

    using value_type = typename T<U...>::value_type;
};

这是std::vector的用法示例:

DEMO (std::vector)

static_assert(
    std::is_same<Test<std::vector, int>::value_type, int>::value, "oops!"); // OK.

Test<std::vector, int> test; // OK

test.insert(test.end(), 11);
test.insert(test.end(), 99);

for(auto it = test.begin(); it != test.end(); ++it){
    std::cout << *it << std::endl;
}

作为另一个示例,此包装器类还可以与std::map一起使用,如下所示:

DEMO (std::map)

static_assert(
    std::is_same<Test<std::map, int, int>::value_type, std::pair<const int, int>>::value, "oops!"); // OK.

Test<std::map, int, int> test; // OK

test.insert(std::make_pair(1, 11));
test.insert(std::make_pair(2, 99));

for(auto it = test.begin(); it!= test.end(); ++it){
    std::cout << it->first << ", " << it->second << std::endl;
}

最后,这是第二个片段的固定版本:

DEMO (std::vector)

DEMO (std::set)

template <class T>
class Test
{
    T list;

public:
    template<class ...V>
    void insert(V&& ...element) {
        list.insert(std::forward<V>(element)...);
    }

    typename T::iterator begin() noexcept {
        return list.begin();
    }

    typename T::iterator end() noexcept {
        return list.end();
    }

    using value_type = typename T::value_type;
};

答案 1 :(得分:3)

最简单的一个是

bool erase_replace_seq (vector <int>& data, int start, int end, int replace)
{
    bool result = false;
if ((start<data.size () && start>=0)  && (end < data.size () && end >=0 && end >= start))
    {
        auto iter = data.erase (data.begin () + start, data.begin () + end);
        data.insert (iter, replace);
        result = true;
    }

    return result;
}

和/或,为了完整性和移动语义合规性:

template <typename T>
class Test {
    ....
    void insert(const typename T::value_type& element);