C++ tuple utils

I’ve recently been been writing lots of modern C++ code with variadic templates. For instance , I’ve been trying to make libsigc++ use variadic templates instead of being a mess of generated code.

I often find myself needing utility functions and type traits to manipulate tuples, but the C++ standard library still only offers std::tuple_cat(). Writing these is awkward and that often stops me from experimenting quickly.

So I’m gradually gathering this code together in a little murrayc-tuple-utils library. I’d gladly change the name if this gets any use. Really, I’m surprised that nothing like this seems to exist already, apart from as part of larger projects such as boost::hana and boost::fusion. But boost is a really awkward dependency and those are larger projects with much grander goals.

So far murrayc-tuple-utils has:

  • tuple_cdr(): Removes the first element.
  • tuple_start<N>(): Takes the first N elements.
  • tuple_end<N>(): Takes the last N elements.
  • tuple_subset<pos, len>: Takes len elements, starting at pos.
  • tuple_interlace<T1, T2>: Takes elements from each tuple, interlacing (or zipping) them together.

For each of them, there are also type traits, such as tuple_type_cdr<>::type, though these are not so necessary now that C++14 has decltype(auto) for return types.

These are just enough code to make things work enough for me when I’m in a rush. I’m sure they can be improved, and maybe this is how to get those patches and pull requests.

The project has a complete autotools build structure, with “make check” tests, Doxygen documentation building, a pkg-config .pc file, etc, so you can try it out, improve it, and add to it, without having to mess around with that stuff.

13 thoughts on “C++ tuple utils

  1. You are fighting the way C++ tuples were meant to be used: as vectors
    indexed by a number.

    Clearly you have some kind of list/scheme background and want to treat
    tuples as lists. There’s nothing wrong with that, but since it wasn’t the
    way they were intended to be used you find no existing support.

    1. This makes no sense; vectors are variable-sized homogeneous sequences, tuples are fixed-size heterogeneous sequences. “Vectors indexed by a number”, i.e. fixed-size homogeneous sequences, are already in C++ – they’re called arrays.

    2. Variadic templates cannot be accessed by indexes, as this information is only available at compile time. C++ TMP is famous for being functional in nature and the tools described here are very useful to access a specific type parameter from a variadic type parameter list.

  2. > Variadic templates cannot be accessed by indexes

    Sure it can. That’s what std::get does. See http://en.cppreference.com/w/cpp/utility/tuple/get, for example. It all happens in the type system and therefore at compile time.

    As for why tuples are like (compile-time) vector, see the printing code at http://www.joshuaburkholder.com/blog/2014/07/16/printing-tuples-in-cpp-2011/ That code clearly (well, as “clearly” as any template code ever gets) loops over indices of the tuple — precisely as you would make a loop over a std::vector other than compile-time vs. run-time.

    The standard provides std::get and the “sizeof…” operator. Those are of the same nature as std::vector’s operator[] and size() methods. While you can use those to emulate scheme-like lists, doing so will hit you badly in compile-time cpu and memory usage.

  3. You should check out this post here:

    http://pfultz2.com/blog/2015/09/12/power-of-unpack/

    It shows how to implement these algorithms in under 100 lines of code using the Fit library(). The Fit library is a small dependency and is portable(unlike Boost.Hana). In addition, I have started writing a library that implements these algorithms called Hero:

    https://github.com/pfultz2/Hero

    Plus, each algorithm has a corresponding view, which is helpful in avoiding extra copies. Currently, it is still a WIP, but I hope to have it finished sometime soon.

    1. Thanks. I haven’t taken the time to play with boost::hana other than watching your fascinating CppCon 2015 talk. I don’t at all mean to suggest that this little pile of thrown together code is in any way better or even remotely as good as boost::hana. That would be insanely unlikely. And I’m not suggesting that people use it and trust it immediately as it is. I do mean to suggest that people might improve it. I know of no better way to make code better than to let people improve it. Sorry if that’s not clear from the blog post.

      I just needed some completely standalone code (that I can copy into another project) to do this stuff so I could make progress on a project. I’m aware that they are doing unnecessary copying and I’m sure that there are better ways to implement them. At the moment, I’m focused on seeing if I can even make that project (libsigc++) work at all with variadic templates and tuples. I think it will work. But I’m not prioritizing getting the tuple utilities any more than working.

      I’m particularly pleased to hear that boost::hana can be used without the rest of boost and without boost’s monolothic release process. Does it even have a pkg-config file?

      1. Also, does boost::hana have equivalents for the *_type_*::type (I couldn’t think of better names) type traits in murrayc-tuple-utils? I seem to need them so far, though I hope I won’t need them when I’m finished.

  4. 1. C++ tuples were “meant” to be used as a vector indexed as a number? Citation needed, please.

    In particular, C++17 allows them to be indexed by _type_, so even the STL maintainers see multiple uses for it.

    Good tools have many uses…

    2. Why not call it just `tuple_utils`? (Naming C++ projects with dashes in the name is perhaps unwise because you can’t use the same name within C++…)

    3. Once you’re in the `tuple_utils` subdirectory, why name each file again with a `tuple_` prefix? You already have a unique name.

    4. The code is hard to evaluate because of the long lines – too long to fix into a github window without scrolling sideways.

    Honestly, I restrict everything that goes out to third parties to 80 columns still, even though I have a huge monitor. Such files are compatible with *every* C++ project in existence and no one ever complains. “No complaints” are definitely a guiding force for my work. :-)

    1. > . C++ tuples were “meant” to be used as a vector indexed as a number? Citation needed, please

      I don’t think you are replying to me there.

      > Why not call it just `tuple_utils`

      Because it’s not ready.

      > The code is hard to evaluate because of the long lines

      Sure. Patches and pull requests are welcome if that’s important to you. Some build rules to run clang-tidy on the code base would be fine too.

Comments are closed.