реализация вариадной почтовой функции с константностью - PullRequest
4 голосов
/ 09 июля 2011

Я пытаюсь реализовать функцию zip.Каждый из параметров zip - это wrapped<Ti>, где Ti изменяется от параметра к параметру.

zip принимает эти wrapped<Ti> с и выдает 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?

Ответы [ 3 ]

1 голос
/ 09 июля 2011

Вот решение, к которому я пришел:

#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>... не такое удовлетворительное решение, но оно работает.

1 голос
/ 09 июля 2011

Правда, у меня нет компилятора 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));
0 голосов
/ 09 июля 2011
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+
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...