16

私は次のことをしたい:

std::vector<int> a = {1,2,3}, b = {4,5,6}, c = {7,8,9};

for(auto&& i : join(a,b,c)) {
  i += 1
  std::cout << i;  // -> 2345678910
}

私は使用してみboost::range::joinました、これはうまくいきます:

auto r = boost::join(a,b);
for(auto&& i : boost::join(r,c)) {
  i += 1;
  std::cout << i;  // -> 2345678910
}

結合の連鎖、操作の読み取りは次のように機能します。

for(auto&& i : boost::join(boost::join(a,b),c))
  std::cout << i;  // -> 123456789

ただし、書き込みは機能しません。

for(auto&& i : boost::join(boost::join(a,b),c)) {
  i += 1; // Fails  :(
  std::cout << i;  
}

私の可変個引数の結合にも同じ問題があります。つまり、読み取りには機能しますが、書き込みには機能しません。

template<class C> C&& join(C&& c) { return c; }

template<class C, class D, class... Args>
auto join(C&& c, D&& d, Args&&... args)
-> decltype(boost::join(boost::join(std::forward<C>(c), std::forward<D>(d)),
                     join(std::forward<Args>(args)...))) {
return boost::join(boost::join(std::forward<C>(c), std::forward<D>(d)),
                     join(std::forward<Args>(args)...));
}

Mehrdadはコメントで解決策を与えました

template<class C>
auto join(C&& c)
-> decltype(boost::make_iterator_range(std::begin(c),std::end(c))) {
return boost::make_iterator_range(std::begin(c),std::end(c));
}

template<class C, class D, class... Args>
auto join(C&& c, D&& d, Args&&... args)
-> decltype(boost::join(boost::join(boost::make_iterator_range(std::begin(c),std::end(c)),
                                 boost::make_iterator_range(std::begin(d),std::end(d))),
                     join(std::forward<Args>(args)...))) {
  return boost::join(boost::join(boost::make_iterator_range(std::begin(c),std::end(c)),
                                 boost::make_iterator_range(std::begin(d),std::end(d))),
                     join(std::forward<Args>(args)...));
}
4

1 に答える 1

13

boost::join には2 つのオーバーロードがあります

template<typename SinglePassRange1, typename SinglePassRange2>
joined_range<const SinglePassRange1, const SinglePassRange2>
join(const SinglePassRange1& rng1, const SinglePassRange2& rng2)

template<typename SinglePassRange1, typename SinglePassRange2>
joined_range<SinglePassRange1, SinglePassRange2>
join(SinglePassRange1& rng1, SinglePassRange2& rng2);

これを行うと

for(auto&& i : boost::join(boost::join(a,b), c)) {
           //  ^^^^        ^^^^ temporary here
           //   ||
           //  calls the const ref overload

一時的なjoined_rangeものを取得し、それらは const 参照にのみバインドできるため、変更を許可しない範囲を返す最初のオーバーロードが選択されます。

一時的なものを避けると、これを回避できます。

#include <boost/range.hpp>
#include <boost/range/join.hpp>

int main()
{
    std::vector<int> a = {1,2,3}, b = {4,5,6}, c = {7,8,9};
    auto range = boost::join(a,b);

    for(int& i : boost::join(range,c)) {
        i += 1;
        std::cout << i;
    }
}

ライブデモ。

私はあなたの変数関数を調べていませんが、問題はおそらく似ています。

于 2013-01-16T20:08:12.270 に答える