v.oddou
v.oddou

Reputation: 6775

"use of class template requires template argument list" error, even though template of template is used, therefore template class is expected

context/ultimate wish (though barely relevant to the question)

do a benchmark for lots of sizes for lots of containers for lots of element types.

at least I would like to have a template combiner of type-lists to create a foreach(foreach) scheme. (obtain a 16-elements list from two 4-elems lists.)

I do not have boost mpl, nor C++11. :'(

I am trying at first to create a list of pairs with the first element of list1 being repeated all over a new list, where second elements would be copies of elements of list2. that would be the first step. (final goal is to obtain a list of the size of list1, made of list of pairs with all the combinations.)

anyway I bump into a little practical issue, where I have a Transform meta function that accepts only a Predicate with 1 template argument as the transformer function.

But I wish to create a closure from a 2 argument metafunction to one that takes 1 argument but has stored the first during typedefing.

I did that:

template < template <class> class Principal, typename TypeListN_T >
struct Transform
{
    typedef typename detail::TransformAux<Principal, TypeListN_T, EmptyT, Length<TypeListN_T>::value - 1 >::Value_t Value_t;
};


template < typename T1, typename T2 >
struct Pair
{
    typedef T1 First_t;
    typedef T2 Second_t;
};

template < typename T1, typename T2 >
struct MakePair
{
    typedef Pair< T1, T2 > Value_t;
};

template < template < class, class > class Binary, typename T >
struct Unarify
{
    template < typename T2 >
    struct U
    {
        typedef Binary< T, T2 > value_t;
    };
};

// create a list of " Pair<Tfirst, List::At< i > > " for each i in List.
template < typename TFirst, typename List >
struct EmplaceListInSecond
{
    typedef typename List::Head_t ToPlaceRightT;
    typedef TFirst                ToPlaceLeftT;

    template < typename T >
    struct UnaryPairMaker : Unarify< MakePair, ToPlaceLeftT >::U
    {
    };

    typedef typename Transform< UnaryPairMaker, List >::Value_t Value_t;
};

The real problem

the compiler (visual studio 2012), is giving me:

1>..\BenchmarkApp.cpp(648): error C2955: 'Meta::Unarify::U' : use of class template requires template argument list

this happens on the last-fifth line in the code extract. on this line:

struct UnaryPairMaker : Unarify< MakePair, ToPlaceLeftT >::U

Which I find super strange, because I am placing a 2-args template class (MakePair) into the template-template parameter of Unarify, where normally it should be accepted.

It should be accepted because the first template argument of Unarify is supposed to be a template class. And the compiler complains that it .... is a template class....

what the hell is going on here ?

EDIT : Solution

Here guys/girls for you future readers, like WhozCraig and Marco A. both mentioned, the problem was ::U and not MakePair. Crazy quick code scanning ability guys, respect.

template < template < class, class > class Binary, typename T >
struct Unarify
{
    template < typename T2 >
    struct U
    {
        // little fix here compared to previous version ::Value_t wasnt called.
        typedef typename Binary< T, T2 >::Value_t Value_t;
    };
};

// create a list of " Pair<Tfirst, List::At< i > > " for each i in List.
template < typename TFirst, typename List >
struct EmplaceListInSecond
{
    typedef typename List::Head_t ToPlaceRightT;
    typedef TFirst                ToPlaceLeftT;

    // big fix here, ::U is a template class that needed an argument (INDEED !!)
    // I was mistakenly taking the message for a MakePair problem, maybe would
    // have it been cland I would have seen the column number. well whatever...
    // T is the actual PLACEHOLDER that will accept the values passed during
    // visitation by the Transform function, and it is the type we want for U's T2 !    
    template < typename T >
    struct UnaryPairMaker : Unarify< MakePair, ToPlaceLeftT >::template U<T>
    {
    };

    typedef typename Transform< UnaryPairMaker, List >::Value_t Value_t;
};

There we go. it IS POSSIBLE MAN ! Yes, it is possible to close a type from a binary metafunction into an unary metafunction passable to a meta-algorithm that takes a unary metafunction as a functor. hehe. C++ just freaking rocks.

Upvotes: 1

Views: 2510

Answers (1)

Marco A.
Marco A.

Reputation: 43662

U requires an argument (see its declaration)

template < typename T2 >
    struct U
    {

you're not passing any in the line

template < typename T >
    struct UnaryPairMaker : Unarify< MakePair, ToPlaceLeftT >::U

A possible solution:

template < typename T >
    struct UnaryPairMaker : Unarify< MakePair, ToPlaceLeftT >::template U<T>
    {
    };

Also note the template keyword: that is not optional if your compiler follows the standard

When the name of a member template specialization appears after . or -> in a postfix-expression, or after nested-name-specifier in a qualified-id, and the postfix-expression or qualified-id explicitly depends on a template-parameter (14.6.2), the member template name must be prefixed by the keyword template. Otherwise the name is assumed to name a non-template.

Upvotes: 2

Related Questions