Search code examples
c++c++20variadic-templates

Cast a function arguments to a given tuple element types


Is there a simple way to implement a function like this

template <typename Tuple, typename... Args>
constexpr auto make_similar_tuple(Args&&... args);

that casts its arguments to a given tuple element types preserving CV qualifiers and references and returns a tuple of that arguments.

so that

using Tuple = std::tuple<std::string, int>;

make_similar_tuple<Tuple, std::string, int> returns std::tuple<std::string, int>
make_similar_tuple<Tuple, std::string&, int> returns std::tuple<std::string&, int>    
make_similar_tuple<Tuple, std::string&, int8_t> returns std::tuple<std::string&, int>    
make_similar_tuple<Tuple, const char*, int8_t> returns std::tuple<std::string, int>    
make_similar_tuple<Tuple, const std::string&, int> returns std::tuple<const std::string&, int>    

An example of a user code:

using Tuple = std::tuple<std::string, int>;
int i = 10;
auto t = make_similar_tuple<Tuple>("a", i);
static_assert(std::is_same_v<decltype(t), std::tuple<std::string, int&>>);
assert(t == std::make_tuple(std::string("a"), 10));

The implementation should cast "a" to std::string as in the code below:

#include <iostream>

int main()
{
    auto a = static_cast<std::string>("a");

    std::cout << a << std::endl;

    return 0;
}

but the second element remains the reference becuase i is lvalue.


Solution

  • It seems that you can get the corresponding type of the returned tuple through common_reference_t<T&, Args>

    #include <tuple>
    
    template <typename Tuple, typename... Args>
    constexpr auto
    make_similar_tuple(Args&&... args) {
      static_assert(std::tuple_size_v<Tuple> == sizeof...(Args));
      return [&]<size_t... Is>(std::index_sequence<Is...>) {
        return std::tuple<
          std::common_reference_t<
              std::tuple_element_t<Is, Tuple>&, Args
            >...
        >(std::forward<Args>(args)...);
      }(std::index_sequence_for<Args...>{});
    }
    

    Demo with your testcases