0

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?

4
  • If you tag the question C++17 it's about realizing something in C++17. But it seems you want to realize it in an older version: tag it the version you are using. std::tie was already in C++14. Many of the tuple stuff you mention since C++11.
    – JHBonarius
    Commented Jan 13, 2022 at 7:54
  • std::make_from_tuple is a c++17 feature Commented Jan 13, 2022 at 7:57
  • It's not clear form the question that you are only talking about make_form_tuple, and still: you want to realize it in another version. So tag which version you want. By the way as make_from_tuple is a library feature, not a language feature, you can always make your own implementation of it, based on the standardized one.
    – JHBonarius
    Commented Jan 13, 2022 at 7:58
  • I removed the c++17 tag as per your suggestion, because this is not something I'd like to realize in c++17. However I would not like to pin an exact standard to the question. Commented Jan 13, 2022 at 8:02

1 Answer 1

1

std::bind does something completely different. Quoting cppreference

The function template bind generates a forwarding call wrapper for f. Calling this wrapper is equivalent to invoking f with some of its arguments bound to args.

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...

1
  • Thank you, great answer! Seems there's no black magic to it, and the implementation is part of the standard for a good reason. Commented Jan 13, 2022 at 8:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.