【问题标题】:Decrease size of container of non-default-constructible elements using unary resize使用一元调整大小减小非默认可构造元素容器的大小
【发布时间】:2016-04-21 10:28:50
【问题描述】:

使用push_back/emplace_back(罕见的push_front/emplace_front 甚至push_after/emplace_after)我几乎可以从STL 中填充任何容器。甚至是非默认可构造元素的容器。减小尺寸只需要元素的析构函数(此外,容器必须要求元素为Destructible)。但我不能简单地使用resize(如果存在)来减小非默认可构造元素容器的大小。相反,我必须使用一种解决方法,即使对于它们中最不严格的(特殊功能):std::list

#include <list>

#include <cstdlib>

int
main()
{
    // construct
    std::list< std::reference_wrapper< int > > l;
    // fill
    int i{};
    l.emplace_back(i);
    int j{};
    l.emplace_back(j);
    // save intermediate state for future
    std::size_t const size = l.size();
    // continue appending
    int k{};
    l.emplace_back(k);
    // now I want to rollback to saved state
    //l.resize(size); // just need to call the destructors, but illegal due to not default constructible value_type
    // so I have to use a workaround
    for (std::size_t s = l.size(); size < s; --s) {
        l.pop_back();
    }
    return EXIT_SUCCESS;
}

即使是一元 std::list::resize 版本 std::list::value_type 也应该是 DefaultInsertable

我希望一元 resize(std::size_t) 仅用于上述类型的容器中的“减小大小”目的。如果value_type 不是DefaultConstructible,则可以禁止resize(std::size_t, value_type = value_type()) 参与重载决议(例如,使用基类调度)以支持resize(std::size_t)/resize(std::size_t, value_type) 对。如果所需的大小大于当前大小,例如resize(std::size_t),则应该抛出std::bad_alloc。有可能设计吗?

【问题讨论】:

  • 如果你想减小尺寸,你可以使用擦除或拼接之类的东西来拉出你不想要的元素吗?
  • @templatetypedef 一方面erase(甚至std::deque::erase)会导致非擦除元素的引用和迭代器过度失效,另一方面erase需要一个迭代器/迭代器pair - 它更详细,然后只是resize(123);
  • 虽然,对于std::list,没有超出范围的迭代器会失效。

标签: c++ c++11 stl containers default-constructor


【解决方案1】:

value_type 必须是默认可构造的 (DefaultInsertable),因为resize 的接口包含增加和减少大小的代码。即使你只使用了一半的代码,整个函数也必须编译。

还有一个两个参数resize,您可以在其中提供大小增加时要使用的值。在这种情况下,value_type 不必是默认可构造的。

所以,如果你调用l.resize(size, dummy_value),你就解除了对类型的限制。这里的dummy_value 可能是l.front(),或者您可以使用的任何其他元素。如果size参数小于l.size(),无论如何都不会使用。

【讨论】:

  • 这是一个很好的解决方法,除非vlaue_type 是重复制/移动构造的。如果值的数量是有限且受限的怎么办?对于不可复制/移动构造的类型,我仍然可以使用 emplace 函数填充容器,但我无法使用它并且问题仍然有效。
  • 不,resize 的第二个参数不会被移动或复制,除非 resize 操作使容器变大。否则,它只是通过 const 引用传递给函数而不被使用。
  • 第二个参数声明为value_type = value_type()。它不是参考 - 是一个值。 (嗯,直到 C++11)。
  • 好的,那么你有一个旧的实现。在 C++11 中有two different resize functions。在 C++98 中,所有存储在容器中的类型必须默认是可构造的。
  • 你是对的。我使用现代实现,但阅读原始资料。
猜你喜欢
  • 1970-01-01
  • 2017-05-09
  • 2017-07-28
  • 2020-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多