6
\$\begingroup\$

C++11 provides a std::tuple template, but it requires the types of all the fields to be listed individually, which is inconvenient if there are many fields and they're all the same type. If I want a tuple of, say, 10 integers, instead of writing std::tuple<int, int, int, int, int, int, int, int, int, int>, I'd like to be able to just write something like tuple_of<10, int>.

To that end, I've written a template that expands a number into that many copies of a type:

template <unsigned int n, typename T>
struct tuple_of {
private:
 // Adds another copy of T to the list
 template <unsigned int m, typename... Ts>
 struct tuple_builder {
 using type = typename tuple_builder<m-1, T, Ts...>::type;
 };
 // Makes a tuple out of all the copies of T that have been listed
 template <typename... Ts>
 struct tuple_builder<0, Ts...> {
 using type = std::tuple<Ts...>;
 };
public:
 tuple_of() = delete; // Prevent accidental instantiation
 using type = typename tuple_builder<n, T>::type;
};
// Convenience alias
template <unsigned int n, typename T>
using tuple_of_t = typename tuple_of<n, T>::type;

Now you can write either tuple_of<10, int>::type or tuple_of_t<10, int>.

This works, but it seems a little awkward. A few things in particular bother me:

  • I don't really like having to write either ::type or the _t suffix of the convenience alias; I'd rather just write tuple_of<10, int>. I've followed the pattern established by the templates in the standard <type_traits> header — e.g. std::result_of_t<T> is an alias for std::result_of<T>::type — but tuple_of isn't a type trait so I don't know if I should be following that convention.

  • I've made the template a struct because that seems to be the norm for templates used in metaprogramming, but it contains a private helper template that I don't really want to expose, and it's a little weird to have private stuff in a struct.

  • This is the first variadic template I've written, so I'm not sure that my tuple_builder is the most elegant way to build a list of n copies of a type.

  • While testing, I accidentally created an instance of the template type itself, rather than the tuple type it produces, by writing tuple_of<10, int> instead of tuple_of<10, int>::type. To avoid that mistake in the future, I deleted the constructor. I don't know whether that's something templates like this "should" do; the templates in <type_traits> don't have deleted constructors.

Can this template be improved?

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Jan 4, 2015 at 23:31
\$\endgroup\$
4
  • 6
    \$\begingroup\$ What is wrong with std::array<int, 10>? \$\endgroup\$ Commented Jan 4, 2015 at 23:46
  • \$\begingroup\$ That could probably work, but I'd like to have compile-time checking that I'm only accessing valid elements. With std::array, it looks like operator[] doesn't prevent out-of-bounds access, and at() checks at runtime. Using std::get<n> on a tuple will fail to compile if n is past the end of the tuple. \$\endgroup\$ Commented Jan 4, 2015 at 23:50
  • 1
    \$\begingroup\$ Ahh, nevermind, I see that std::get works with std::array too. And the page on cppreference.com even mentions that "an array can also be used as a tuple of N elements of the same type." \$\endgroup\$ Commented Jan 5, 2015 at 0:33
  • \$\begingroup\$ If the types are all the same. Then we are talking about an array. \$\endgroup\$ Commented Jan 5, 2015 at 1:54

1 Answer 1

1
\$\begingroup\$

As nwp pointed out in a comment, std::array is a better choice for this. I didn't need to write this template at all.

answered Jan 6, 2015 at 4:55
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.