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?
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.
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With