Борьба с Boost.Mp11: «ожидал шаблон класса, получил« T »»

Я пытаюсь проверить неспециализированных Уникальность кортежа специализированных типов с использованием 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;
}

Вы можете запустить приведенный выше код на Coliru. Для каждого типа весь список перебирается, пытаясь найти неспециализированный эквивалент, поэтому {std::vector<int>, std::deque<float>, std::tuple<Foo>} пройдет, но {std::vector<int>, std::vector<float>, std::tuple<Foo>} не будет.

Однако я получаю эту ошибку:

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'

Но я не понимаю как T неизвестно — кто-нибудь может увидеть, что я делаю не так?

3

Решение

Работает на 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;
}
1

Другие решения

Немедленная ошибка в …

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>
>;

Если мы сравним это с …

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

… мы видим, что код переименовывается T где шаблон U ожидается. Но внесение поправок только исправит ошибку в другом месте, потому что теперь boost.mp не получит ожидаемый тип предиката. Боюсь, я не слишком знаком с библиотекой, чтобы рассказать вам, как получить рабочую версию помимо этого.

3