c++c++17template-meta-programmingstdtupleconversion-operator

C++ turn a std::tuple<char, char, char> into a std::string?


I am writing a lightweight parser combinator library (akin to Boost::Spirit) as hobby project.

One thing I'd like to do, is to automatically be able to convert a Result<std::tuple<char>>, Result<std::tuple<char, char>>, etc. into a std::string.

And similarly, if having e.g. a Result<std::tuple<int, int>> I'd like to be able to convert it to a Result<std::vector<int>> or more generally for any tuple containing zero or more elements of the same type T I'd like to be able to convert it automatically to a Result<Container<T>>.

How does one tackle something like this? I attempted for instance:

  template<typename Container>
  Result<decltype(std::make_from_tuple<Container>(std::declval<T>()))> () const {
      Result{Container{std::make_from_tuple<std::initializer_list<typename std::tuple_element<0, T>::type>> (std::get<T>(*this))}};
  }

but this does not work, as it turns out that it's not possible to create an initializer list programmatically like this.


Solution

  • template <typename... Ts>
    std::string tuple_to_string(const std::tuple<Ts...>& t)
    {
        return std::apply([](auto... cs)
        { 
            return std::string{cs...}; 
        }, t);
    }
    

    live example on godbolt.org


    More generic solution:

    template <typename T, typename... Ts>
    T tuple_to_container(const std::tuple<Ts...>& t)
    {
        return std::apply([](auto... cs){ return T{cs...}; }, t);
    }
    

    Usage:

    std::tuple test0{'a', 'b', 'c'};
    std::tuple test1{'a', 'b', 'c', 'd', 'e', 'f'};
    
    std::cout << tuple_to_container<std::string>(test0) << '\n'
              << tuple_to_container<std::string>(test1) << '\n';
    
    std::tuple test2{0, 1, 2, 3};
    auto converted = tuple_to_container<std::vector<int>>(test2);
    assert(converted == (std::vector{0, 1, 2, 3}));