タプルを使用して可変数の項目 (この場合は転送先のパラメータemplace_back
)を簡単に渡し、タプルをアンパックして戻すちょっとしたテクニックを使うのが一般的です。そのため、意味back_emplacer
のあるタプル ファクトリ関数 ( std::make_tuple
、std::tie
、のいずれか) を使用するようにユーザーに要求することで、ユーティリティを作成することができます。std::forward_as_tuple
#include <type_traits>
#include <tuple>
// Reusable utilites
template<typename T>
using RemoveReference = typename std::remove_reference<T>::type;
template<typename T>
using Bare = typename std::remove_cv<RemoveReference<T>>::type;
template<typename Out, typename In>
using WithValueCategoryOf = typename std::conditional<
std::is_lvalue_reference<In>::value
, typename std::add_lvalue_reference<Out>::type
, typename std::conditional<
std::is_rvalue_reference<Out>::value
, typename std::add_rvalue_reference<Out>::type
, Out
>::type
>::type;
template<int N, typename Tuple>
using TupleElement = WithValueCategoryOf<
typename std::tuple_element<N, RemoveReference<Tuple>>::type
, Tuple
>;
// Utilities to unpack a tuple
template<int... N>
struct indices {
using next = indices<N..., sizeof...(N)>;
};
template<int N>
struct build_indices {
using type = typename build_indices<N - 1>::type::next;
};
template<>
struct build_indices<0> {
using type = indices<>;
};
template<typename Tuple>
constexpr
typename build_indices<std::tuple_size<Bare<Tuple>>::value>::type
make_indices() { return {}; }
template<typename Container>
class back_emplace_iterator {
public:
explicit back_emplace_iterator(Container& container)
: container(&container)
{}
template<
typename Tuple
// It's important that a member like operator= be constrained
// in this case the constraint is delegated to emplace,
// where it can more easily be expressed (by expanding the tuple)
, typename = decltype( emplace(std::declval<Tuple>(), make_indices<Tuple>()) )
>
back_emplace_iterator& operator=(Tuple&& tuple)
{
emplace(*container, std::forward<Tuple>(tuple), make_indices<Tuple>());
return *this;
}
template<
typename Tuple
, int... Indices
, typename std::enable_if<
std::is_constructible<
typename Container::value_type
, TupleElement<Indices, Tuple>...
>::value
, int
>::type...
>
void emplace(Tuple&& tuple, indices<Indices...>)
{
using std::get;
container->emplace_back(get<Indices>(std::forward<Tuple>(tuple))...);
}
// Mimic interface of std::back_insert_iterator
back_emplace_iterator& operator*() { return *this; }
back_emplace_iterator& operator++() { return *this; }
back_emplace_iterator operator++(int) { return *this; }
private:
Container* container;
};
template<typename Container>
back_emplace_iterator<Container> back_emplacer(Container& c)
{ return back_emplace_iterator<Container> { c }; }
コードのデモが利用可能です。あなたの場合、あなたは電話したいと思いますstd::fill_n(back_emplacer(v), 10, std::forward_as_tuple(1, 1.0));
(std::make_tuple
も受け入れられます)。また、通常のイテレータを使用して機能を完成させたい場合もあります。そのためには Boost.Iterators をお勧めします。
ただし、このようなユーティリティを .NET と一緒に使用してもあまり効果がないことを強調しておく必要がありますstd::fill_n
。Foo
あなたの場合、参照のタプル(を使用する場合は値のタプル)を優先して、一時的なの構築を保存しますstd::make_tuple
。back_emplacer
役に立つ他のアルゴリズムを見つけるのは読者に任せます。