The standard templates std::pair and std::array are special cases of std::tuple, and it stands to reason that they should have a very
I'm not sure why it's not there. Previously, I thought that the implementation wouldn't be possible, given the current varadic template syntax, but I realized that it can be done if it's broken into pieces.
If they had defined an interface like this:
template
tuple(piecewise_construct, T&&... t);
And made it a requirement that the arguments are something that you can use std::get to access the arguments (basically, tuples, pairs, arrays). There would have to be extra checks to verify there isn't a mismatch between the number of arguments given and the number of elements in the tuple.
Edit: This problem has been bothering me since I read it. And I've created the following class, it is derived from std::tuple, and has no data members, so you can assign it to the tuple and the slicing is harmless. The current version requires that the elements be moveable or copyable, as it creates a temporary and then inserts that into the tuple. If you were a tuple implementer, it should be possible to eliminate even that move.
namespace detail
{
template
struct index {
typedef index next;
};
template
struct build_index {
typedef typename build_index::type::next type;
};
template<>
struct build_index<0> {
typedef index<> type;
};
template
struct tuple_index {
typedef typename build_index<
std::tuple_size::type>::value>::type type;
};
}
template
class piecewise_tuple: public std::tuple
{
typedef std::tuple base_type;
template
static typename std::tuple_element::type
construct(std::tuple&& args, detail::index)
{
typedef typename std::tuple_element::type result_type;
return result_type(std::get(std::move(args))...);
}
template
piecewise_tuple(detail::index, ArgTuple&& element_args)
: base_type( construct( std::get(std::forward(element_args)),
typename detail::tuple_index< typename std::tuple_element::type >::type >::type() )...)
{
}
public:
piecewise_tuple() = default;
// For non-piecewise constructors, forward them
template
piecewise_tuple(Args&&... args) : base_type(std::forward(args)...) {}
template
piecewise_tuple(std::piecewise_construct_t, T&&... args) :
piecewise_tuple(typename detail::tuple_index::type(),
std::forward_as_tuple(std::forward(args)...))
{
}
};
// Usage example
int main()
{
int i = 5;
std::unique_ptr up(new int(0));
piecewise_tuple, double, std::unique_ptr, int& >
p(std::piecewise_construct,
std::forward_as_tuple(1,2),
std::forward_as_tuple(4.3),
std::forward_as_tuple(std::move(up)),
std::forward_as_tuple(i));
return 0;
}