cmannett85
cmannett85

Reputation: 22346

Struggling with Boost.Mp11: "expected a class template, got 'T'"

I am trying to check the unspecialised uniqueness of a tuple of specialised types using Boost.Mp11:

#include <iostream>
#include <vector>
#include <deque>
#include <tuple>

#include <boost/mp11/algorithm.hpp>

namespace
{
template <typename T, template <typename...> typename U>
struct is_specialisation : std::false_type {};

template <template <typename...> typename U, typename... Args>
struct is_specialisation<U<Args...>, U> : std::true_type {};

template <template <typename...> typename U>
struct is_specialisation_meta
{
    template <typename T>
    using type = is_specialisation<T, U>;
};

template <typename TypeList>
struct unique_specialisation
{
    template <typename T>
    using type = std::is_same<
        boost::mp11::mp_count_if<
            TypeList,
            is_specialisation_meta<T>::template type // Error!
        >,
        boost::mp11::mp_size_t<1>
    >;
};
}

int main()
{
    using types = std::tuple<
        std::vector<int>,
        std::deque<int>,
        std::tuple<int>
    >;

    using all_unique_specialisations = boost::mp11::mp_all_of<
        types,
        unique_specialisation<types>::template type
    >;

    std::cout << std::boolalpha << all_unique_specialisations::value << std::endl;

    return EXIT_SUCCESS;
}

You can run the above code on Coliru. For each type, the whole list is iterated over trying to find an unspecialised equivalent, so {std::vector<int>, std::deque<float>, std::tuple<Foo>} would pass but {std::vector<int>, std::vector<float>, std::tuple<Foo>} would not.

However I get this error:

main.cpp:30:37: error: type/value mismatch at argument 1 in template parameter list for 'template<template<class ...> class U> struct {anonymous}::is_specialisation_meta'
             is_specialisation_meta<T>::template type
                                     ^
main.cpp:30:37: note:   expected a class template, got 'T'

But I don't understand how T is unknown - can anyone see what I am doing wrong?

Upvotes: 4

Views: 438

Answers (2)

llonesmiz
llonesmiz

Reputation: 155

Running on Wandbox

#include <iostream>
#include <vector>
#include <deque>
#include <tuple>

#include <boost/mp11/algorithm.hpp>

namespace
{
template <typename T, template <typename...> typename U>
struct is_specialisation : std::false_type {};

template <template <typename...> typename U, typename... Args>
struct is_specialisation<U<Args...>, U> : std::true_type {};

template <typename T> struct is_specialisation_meta;//ADDED

template <template <typename... > typename U, typename... Args>//CHANGED
struct is_specialisation_meta<U<Args...>>
{
    template <typename T>
    using type = is_specialisation<T, U>;
};

template <typename TypeList>
struct unique_specialisation
{
    template <typename T>
    using type = std::is_same<
        boost::mp11::mp_count_if<
            TypeList,
            is_specialisation_meta<T>::template type // Error!
        >,
        boost::mp11::mp_size_t<1>
    >;
};
}

int main()
{
    using types = std::tuple<
        std::vector<int>,
        std::deque<int>,
        std::tuple<int>
    >;

    using types2 = std::tuple<
        std::vector<int>,
        std::vector<float>,
        std::tuple<int>
    >;

    using all_unique_specialisations = boost::mp11::mp_all_of<
        types,
        unique_specialisation<types>::template type
    >;

    using all_unique_specialisations2 = boost::mp11::mp_all_of<
        types2,
        unique_specialisation<types2>::template type
    >;

    std::cout << std::boolalpha << all_unique_specialisations::value << std::endl;
    std::cout << std::boolalpha << all_unique_specialisations2::value << std::endl;

    return EXIT_SUCCESS;
}

Upvotes: 2

The immediate error is in...

template <typename T>
using type = std::is_same<
    boost::mp11::mp_count_if<
        TypeList,
        is_specialisation_meta<T>::template type // Error!
    >,
    boost::mp11::mp_size_t<1>
>;

If we compare it against...

template <template <typename...> typename U>
struct is_specialisation_meta

... we see that the code passes a typename T where a template U is expected. But amending that only shifts the error elsewhere, because now boost.mp is not going to get the predicate type it expects. I'm afraid I'm not too familiar with the library to tell you how to get a working version beyond this.

Upvotes: 4

Related Questions