Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::tuple as template argument?

I'm trying to write an std::sort template compare class that should receive an unknown number of tuples (variadic template). Each tuple should be consisted of a column (some type we have in our code) and a bool, specifying if this column should be sorted in ascending or descending order.

Basically, I want something similar to this:

// doesn't compile - conceptual code
template <typename std::tuple<Col, bool>>
struct Comparator
{
    bool operator() (int lhs, int rhs)
    {
         // lhs and rhs are row indices. Depending on the columns
         // and the bools received, decide which index should come first
    } 
}

Is this sort of thing possible in C++ 11?

like image 283
Shmoopy Avatar asked May 04 '15 10:05

Shmoopy


2 Answers

Yes, it's possible - you want a partial specialization of Comparator:

template <typename T>
struct Comparator;

template <typename Col>
struct Comparator<std::tuple<Col, bool>>
{
    // ...
};
like image 188
Barry Avatar answered Oct 10 '22 16:10

Barry


Is this possible? Yes, but you need some fairly ugly template tricks for it.

//a trait for checking if a type is of the form std::tuple<T,bool>
template <class Tuple>
struct is_col_bool_tuple : false_type{};

template <typename Col>
struct is_col_bool_tuple<std::tuple<Col,bool>> : true_type{};

//a helper struct for checking if all the values in a boolean pack are true
template<bool...> struct bool_pack;
template<bool... bs> 
using all_true = std::is_same<bool_pack<bs..., true>, bool_pack<true, bs...>>;

//a trait to check if a list of types are all of the form std::tuple<T,bool>
template <class... Tuples>
using are_col_bool_tuples = all_true<is_col_bool_tuple<Tuples>::value...>;

//an incomplete type for when we pass incorrect template arguments
//this impl helper is needed because variadic parameters need to be last
template <typename Enable, class... Tuples>
struct ComparatorImpl;

//our specialized implementation for when the template arguments are correct
template <class... Tuples>
struct ComparatorImpl<std::enable_if_t<are_col_bool_tuples<Tuples...>::value>,
                      Tuples...>
{
     bool operator() (int lhs, int rhs)
    {
         //do your comparison
    } 
};

//a nice alias template for forwarding our types to the SFINAE-checked class template
template <class... Tuples>
using Comparator = ComparatorImpl<void, Tuples...>;
like image 44
TartanLlama Avatar answered Oct 10 '22 17:10

TartanLlama