Partial Constructor arguments from tuple
In C++17 there's std::make_from_tuple
; However that only applies to situations where the number of the elements stored in the tuple matches with that of the constructor.
I was able to concatenate two tuples and use std::make_from_tuple
.
#include <iostream>
#include <utility>
#include <tuple>
class ConstructMe{
public:
ConstructMe(int a_, int b_, int c_)
: a(a_), b(b_), c(c_) { }
private:
int a;
int b, c;
};
int main(){
int a = 1;
std::tuple<int, int> part = std::make_tuple(2,3);
ConstructMe please = std::make_from_tuple<ConstructMe>(
std::tuple_cat(std::make_tuple(a), part)
);
return 0;
}
And after some research ( this question I was able to make it work with references as well with std::tie
as well.
#include <iostream>
#include <utility>
#include <tuple>
class ConstructMe{
public:
ConstructMe(int& a_, int b_, int c_)
: a(a_), b(b_), c(c_) { }
private:
int& a;
int b, c;
};
int main(){
int a = 1;
std::tuple<int, int> part = std::make_tuple(2,3);
ConstructMe please = std::make_from_tuple<ConstructMe>(
std::tuple_cat(std::tie(a), part)
);
return 0;
}
Is there a simpler way to do this ( e.g. with std::bind
) which doesn't require c++17?
std::bind
does something completely different. Quoting cppreference
The function template
bind
generates a forwarding call wrapper forf
. Calling this wrapper is equivalent to invokingf
with some of its arguments bound toargs
.
You can just use the cpp reference link to build your own implementation of the standardized function, e.g. in C++14
#include <iostream>
#include <utility>
#include <tuple>
namespace detail {
template <class T, class Tuple, std::size_t... I>
constexpr T make_from_tuple_impl( Tuple&& t, std::index_sequence<I...> )
{
static_assert(std::is_constructible<T,
decltype(std::get<I>(std::declval<Tuple>()))...>::value);
return T(std::get<I>(std::forward<Tuple>(t))...);
}
} // namespace detail
template <class T, class Tuple>
constexpr T make_from_tuple( Tuple&& t )
{
return detail::make_from_tuple_impl<T>(std::forward<Tuple>(t),
std::make_index_sequence<std::tuple_size<std::remove_reference_t<Tuple>>::value>{});
}
class ConstructMe{
public:
ConstructMe(int& a_, int b_, int c_)
: a(a_), b(b_), c(c_) { }
private:
int& a;
int b, c;
};
int main(){
int a = 1;
std::tuple<int, int> part = std::make_tuple(2,3);
ConstructMe please = make_from_tuple<ConstructMe>(
std::tuple_cat(std::tie(a), part)
);
}
If you want to go back more language versions, you have to do more by hand. It will be harder and harder, especially if you want to go before C++11...