【问题标题】:Is there a rebind for containers?容器有重新绑定吗?
【发布时间】:2018-10-23 03:07:28
【问题描述】:

在C++标准库allocators可以反弹。

std::allocator<int>::rebind<double>::other 给出std::allocator<double>

有没有一种简单的方法可以用容器做到这一点?

原因是我有一个将容器元素乘以标量的函数。

template<class Container, typename S>
auto elementwise_multiply_by_scalar(Container const& c, S s){
    Container ret(c.size());
    for(auto& e : ret) e *= s;
    return ret;
}

但是如果e * se不是同一类型,我想这样做:

template<class Container, typename S>
auto elementwise_multiply_by_scalar(Container const& c, S s){
    Container::rebind<decltype(Container::value_type{}*s)> ret(c.size());
    auto it2 = ret.begin();
    for(auto it1 = c.begin(); it1 != c.end(); ++it1, ++it2) *it2 = s * *it1;
    return ret;
}

(我想不清楚为什么我希望输出与输入是同一类容器,但我想这是预期的结果。)

我可以使用模板模板参数(如template&lt;template&lt;typename&gt; class V&gt;),但它似乎也有问题。

我们需要某种container_traits&lt;V&gt;::rebind吗? (例如container_traits&lt;std::vector&lt;double, myallocator&lt;double&gt; &gt;&gt;::rebind&lt;int&gt;::other -> std::vector&lt;int, myallocator&lt;double&gt;::rebind&lt;int&gt;::other&gt;

【问题讨论】:

  • 模板参数 - 是容器类型的固有部分,即vector&lt;int&gt;vector&lt;double&gt; 无关,函数模板使用传递给它的类型实例化。请注意,allocator::rebind 返回不同类型的分配器的新实例,而您希望现有实例更改其类型。 (注意:原则上,可以编写一个可以重新绑定到不同类型的容器类,但它只会在类型更改(“显着”)时封装复制到新容器)
  • 使用 std::transform 并收工
  • @PasserBy,是的,我可以用std::transform 实现循环,但它不能解决问题。
  • std::vector&lt;std::variant&lt;int, double&gt; &gt; 可能是实现这一目标的一种方法,但我必须承认我没有使用std::variant 的经验。

标签: c++ containers typetraits


【解决方案1】:

这样的事情可能会奏效:

struct A
{
};

struct B
{
};

struct C
{
};

C operator *(const A&, const B&)
{
    return C();
}

template <typename Container, typename ValueType>
struct ContainerConverter
{
};

template <typename SourceValueType, typename ValueType>
struct ContainerConverter<std::vector<SourceValueType>, ValueType>
{
    typedef typename std::vector<ValueType> result_type;
};

template <typename Container, typename S>
auto mult(const Container& c, const S& s)
{
    typedef typename Container::value_type source_element;
    typedef decltype(c.front()*s) result_element;
    typename ContainerConverter<Container, result_element>::result_type result;
    std::transform(c.begin(), c.end(), std::back_inserter(result), [&](const source_element& e){ return e * s; } );
    return result;
}

int main()
{
    std::vector<A> a;
    std::vector<C> c = mult(a, B());
}

您需要针对您想要支持的每种容器类型专门化 ContainerConverter

如果您的容器并非全部支持std::back_inserter,请参阅std::transform to arbitrary container

【讨论】:

    猜你喜欢
    • 2016-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-23
    • 2020-04-21
    • 2010-09-14
    • 2015-01-26
    相关资源
    最近更新 更多