Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Position of a type in a variadic template parameter pack

I'm giving C++0x a try and I was wondering how to solve the following problem that came up. I've got a variadic template class:

template<typename... T>
class MyLovelyClass {

 template<typename SomeType>
 void DoSthWithStorageOfSomeType();

 private:
  std::tuple<std::vector<T>...> m_storage;
};

The function there is suppose to do some sort of manipulation on the vector in m_storage tuple that corresponds to the SomeType template argument (or compile time fail if it doesn't). How one can do this?

My idea was to find the index of SomeType in parameter pack and then use std::get to obtain the appropriate vector, but I don't know how to to do the first part.

like image 912
Bartłomiej Siwek Avatar asked May 17 '11 14:05

Bartłomiej Siwek


People also ask

What is Variadic template in C++?

Variadic templates are class or function templates, that can take any variable(zero or more) number of arguments. In C++, templates can have a fixed number of parameters only that have to be specified at the time of declaration.

What is parameter pack in C++?

Parameter packs (C++11) A parameter pack can be a type of parameter for templates. Unlike previous parameters, which can only bind to a single argument, a parameter pack can pack multiple parameters into a single parameter by placing an ellipsis to the left of the parameter name.

What is the use of Variadic templates?

With the variadic templates feature, you can define class or function templates that have any number (including zero) of parameters. To achieve this goal, this feature introduces a kind of parameter called parameter pack to represent a list of zero or more parameters for templates.

What means variadic?

variadic (not comparable) (computing, mathematics, linguistics) Taking a variable number of arguments; especially, taking arbitrarily many arguments.


1 Answers

Here's some code to do a linear search of a tuple for the first type U it finds, and gives a compile-time error if it can't find U. Note if the tuple contains multiple U's it only finds the first one. Not sure if that is the policy you want or not. It returns the compile-time index into the tuple of the first U. Perhaps you could use it as the index into your std::get.

Disclaimer: Thrown together for this answer. Only lightly tested. Edge cases such as an empty tuple have a nasty error message that could be improved. etc.

#include <type_traits>
#include <tuple>

template <class Tuple, class T, std::size_t Index = 0>
struct find_first;

template <std::size_t Index, bool Valid>
struct find_first_final_test
    : public std::integral_constant<std::size_t, Index>
{
};

template <std::size_t Index>
struct find_first_final_test<Index, false>
{
    static_assert(Index == -1, "Type not found in find_first");
};

template <class Head, class T, std::size_t Index>
struct find_first<std::tuple<Head>, T, Index>
    : public find_first_final_test<Index, std::is_same<Head, T>::value>
{
};

template <class Head, class ...Rest, class T, std::size_t Index>
struct find_first<std::tuple<Head, Rest...>, T, Index>
    : public std::conditional<std::is_same<Head, T>::value,
                    std::integral_constant<std::size_t, Index>,
                    find_first<std::tuple<Rest...>, T, Index+1>>::type
{
};

#include <iostream>

int main()
{
    typedef std::tuple<char, int, short> T;
    std::cout << find_first<T, double>::value << '\n';
}
like image 112
Howard Hinnant Avatar answered Sep 18 '22 04:09

Howard Hinnant