4

我正在尝试实现一个zip功能。 zip的参数是 each wrapped<Ti>,其中Ti因参数而异。

zip接受这些wrapped<Ti>s 并产生一个wrapped<tuple<T1&,T2&,...TN&>>,或者换句话说,一个包装tuple了对其参数的引用。引用应保留const-ness。

这是我第一次尝试zip使用一个参数,但通常不起作用:

#include <utility>
#include <tuple>

// implement forward_as_tuple as it is missing on my system
namespace ns
{

template<typename... Types>
  std::tuple<Types&&...>
    forward_as_tuple(Types&&... t)
{
  return std::tuple<Types&&...>(std::forward<Types>(t)...);
}

}

template<typename T>
  struct wrapped
{
  wrapped(T &&x)
    : m_x(std::forward<T>(x))
  {}

  T m_x;
};

template<typename T>
  wrapped<std::tuple<T&&>>
    zip(wrapped<T> &&x)
{
  auto t = ns::forward_as_tuple(std::forward<T>(x.m_x));
  return wrapped<std::tuple<T&&>>(t);
}

int main()
{
  wrapped<int> w1(13);

  wrapped<int> &ref_w1 = w1;

  // OK
  zip(ref_w1);

  const wrapped<int> &cref_w1 = w1;

  // XXX won't compile when passing a const reference
  zip(cref_w1);

  return 0;
}

有没有办法用单一版本的zip?

4

3 回答 3

1

诚然,我没有处理可变参数模板的 C++0x 编译器,所以我无法对其进行测试。但这可能会奏效。

template<typename T>
    struct wrapped
{
    wrapped(T &&x)
    : m_x(std::forward<T>(x))
    {}

    typedef T type;

    T m_x;
};

template<typename... Types>
    wrapped<std::tuple<Types&&...>> zip(wrapped<Types>&&... x)
{
    return wrapped<std::tuple<Types&&...>>(std::tuple<Types&&...>(std::forward<Types>(x.m_x)...));
}

我不完全确定这样打电话是否合法zip

zip(wrapped<T1>(value1), wrapped<T2>(value2));

您可能必须明确限定调用:

zip<T1, T2>(wrapped<T1>(value1), wrapped<T2>(value2));
于 2011-07-09T00:21:51.373 回答
1

这是我得到的解决方案:

#include <utility>
#include <tuple>
#include <cassert>

template<typename T>
  struct wrapped
{
  wrapped(T &&x)
    : m_x(std::forward<T>(x))
  {}

  T m_x;
};

template<typename Tuple>
  wrapped<Tuple> make_wrapped_tuple(Tuple &&x)
{
  return wrapped<Tuple>(std::forward<Tuple>(x));
}

template<typename... WrappedTypes>
  decltype(make_wrapped_tuple(std::forward_as_tuple(std::declval<WrappedTypes>().m_x...)))
    zip(WrappedTypes&&... x)
{
  return make_wrapped_tuple(std::forward_as_tuple(x.m_x...));
}

int main()
{
  wrapped<int> w1(1);
  wrapped<int> w2(2);
  wrapped<int> w3(3);
  wrapped<int> w4(4);

  auto z1 = zip(w1,w2,w3,w4);

  z1.m_x = std::make_tuple(11,22,33,44);

  assert(w1.m_x == 11);
  assert(w2.m_x == 22);
  assert(w3.m_x == 33);
  assert(w4.m_x == 44);

  const wrapped<int> &cref_w1 = w1;

  auto z2 = zip(cref_w1, w2, w3, w4);

  // does not compile, as desired
  // z2.m_x = std::make_tuple(111,222,333,444);

  return 0;
}

zip使用 take而WrappedTypes...不是wrapped<T>...一个令人满意的解决方案,但它确实有效。

于 2011-07-09T08:21:59.023 回答
0
template<typename T>
    struct wrapped
{
    wrapped(T &&x)
    : m_x(std::forward<T>(x))
    {}

    typedef T type;

    T m_x;
};

template<typename... Types>
    wrapped<std::tuple<T&&...>> zip(wrapped<Types>... &&x)
{
    return G+
于 2011-07-09T05:24:02.300 回答