lundi 2 novembre 2015

How can I use template class inside of template class as a template template parameter with a template parameter?

I am trying to use a template class as a template template parameter with another template parameter. As it sounds, it is pretty complicated/twisted and I cannot figure out how to fix the compiler error.

What I wrote is like "std::find_if" but it works for "std::tuple". As the code below shows, it appears to be working when I specify the type for is_same_type_tt but when I try to use a template parameter with is_same_type_tt, the compiler complains:

main.cpp:75:13: error: type/value mismatch at argument 2 in template parameter list for 'template<class TupleType, template<class> class Action> struct tuple_find_if_tt'
      >::value;
      ^

The source code goes like this:

template< typename TypeLookingFor >
struct is_same_type_tt
{
    typedef TypeLookingFor type_looking_for;
    template< typename TypeCompareTo >
    struct type_tt : is_same< type_looking_for, TypeCompareTo >
    {};
};

// base for the recusion
template<
    typename TupleType
    , size_t Index
    , template< typename > class Action >
struct tuple_find_if_recur_tt;

// last in the recursion
template<
    typename TupleLast
    , size_t Index
    , template< typename > class Action >
struct tuple_find_if_recur_tt< tuple< TupleLast >, Index, Action >
    : conditional<
        Action< TupleLast >::value
        , integral_constant< size_t, Index >
        , integral_constant< size_t, -1 > >::type
{};

// recursion
template<
    typename TupleHead, typename... TupleRest
    , size_t Index
    , template< typename > class Action >
struct tuple_find_if_recur_tt<
    tuple< TupleHead, TupleRest... >, Index, Action >
    : conditional<
        Action< TupleHead >::value
        , integral_constant< size_t, Index >
        , tuple_find_if_recur_tt<
            tuple< TupleRest... >
            , Index + 1u
            , Action > >::type
{};

// wrap the recursion
template<
    typename TupleType
    , template< typename > class Action >
struct tuple_find_if_tt
    : tuple_find_if_recur_tt< TupleType, 0u, Action >
{};

As a test, the code below compiles fine:

// this works fine.
static_assert(
    tuple_find_if_tt< tuple< int, float, double >
    , is_same_type_tt< float >::type_tt >::value == 1, "" );

But when I try to use it with one more template parameter, it doesn't work:

// problem starts from here...
template< typename... Types >
struct tuple_indirect_find_tt
{
    typedef tuple< Types... > tuple_type;
    // tuple_type obj_;

    template< typename TypeLookingFor >
    static constexpr size_t find()
    {
        return tuple_find_if_tt<
            tuple_type
            // something is not right below...
            , typename is_same_type_tt< TypeLookingFor >::type_tt
            >::value;
    }
};

// this doesn't work.
static_assert(
    tuple_indirect_find_tt< int, float, double >::find< float >()
    == 1, "" );

In order to get it working, I had to refactor the template classes so that I can do like this:

return tuple_find_if_tt<
    tuple_type
    , is_same_type_tt
    , typename TypeLookingFor // this is separated from is_same_type_tt
    >::value;

The workaround doesn't seem too bad but I still like to know what I did wrong. If this is not a possible approach, I would like to know what C++ standard prevents it.

Thanks for reading.

Aucun commentaire:

Enregistrer un commentaire