Nikos Athanasiou
Nikos Athanasiou

Reputation: 31519

Test whether a type V is among the types of a tuple<...> without variardics

A typical implementation would be like so :

template <typename V, typename T>
struct Is_in_tuple;

template <typename V, typename T0, typename... T>
struct Is_in_tuple <V, tuple<T0, T...> >
{
  static const bool value = Is_in_tuple<V, tuple<T...> >::value;
};

template <typename V, typename... T>
struct Is_in_tuple <V, tuple<V, T...> >
{
  static const bool value = true;
};

template <typename V>
struct Is_in_tuple <V, tuple<> >
{
  static const bool value = false;
};

The problem arises in VS2012 where tuples exist, but variadic templates do not!

Is there a workaround, a way to perform such tests without variadic templates ?

Upvotes: 5

Views: 333

Answers (3)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275385

A completely different approach is based on the size limit.

We rely on the max number of arguments, which is 5 to 10 if I recall correctly.

We write a specialization for each size besides 0 and 1 that invokes smaller sized tuples (half, for min recursion), || the result of each half.

Then we write <T> and <> specializations.

Only fall back on this if other solutions fail, as it stops working the moment you get a standards compliant tuple, or even change the preprocessor symbol of max number of elements for a tuple.

Upvotes: 0

dyp
dyp

Reputation: 39111

Unfortunately, I can't test it on MSVC2012 right now.

#include <type_traits>
#include <tuple>

template<class Needle, class Haystack, int N = std::tuple_size<Haystack>::value>
struct is_any_of
    : std::integral_constant
      <
          bool,
          (std::is_same<Needle, typename std::tuple_element<N-1, Haystack>::type>
           ::value
           || is_any_of<Needle, Haystack, N-1>::value)
      >
{};

template<class Needle, class Haystack>
struct is_any_of<Needle, Haystack, 0>
    : std::false_type
{};

#include <iostream>
int main()
{
    typedef std::tuple<int, int, char, int, int> t0;
    typedef std::tuple<int, int, int, int, int> t1;

    std::cout << std::boolalpha << is_any_of<char, t0>::value << "\n";
    std::cout << std::boolalpha << is_any_of<char, t1>::value << "\n";
}

Upvotes: 4

BatchyX
BatchyX

Reputation: 5114

If VS2012 supports tuple_size and tuple_element, you can use them instead (totally untested code):

template <typename V, typename T, size_t T_end = std::tuple_size<T>::value>
struct Is_in_tuple
  : std::conditional<std::is_same<V, typename std::tuple_element<T_end-1,T>::type>::value,
                     std::true_type, Is_in_tuple<V, T, T_end - 1>>::type {};

template <typename V, typename T>
struct Is_in_tuple <V, T, 0> : std::false_type {};

Upvotes: 4

Related Questions