与 Boost.Mp11 斗争:"expected a class template, got 'T'"

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

我正在尝试检查 unspecialised 使用 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 是如何未知的 - 谁能看出我做错了什么?

直接错误在...

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 不会获得它期望的谓词类型。恐怕我对库不太熟悉,无法告诉您如何获得超出此范围的工作版本。

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