【问题标题】:Struggling with Boost.Mp11: "expected a class template, got 'T'"在 Boost.Mp11 中苦苦挣扎:“期望一个类模板,得到 'T'”
【发布时间】:2018-11-27 08:05:00
【问题描述】:

我正在尝试使用 Boost.Mp11 检查一个特殊类型元组的 unspecialised 唯一性:

#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&lt;int&gt;, std::deque&lt;float&gt;, std::tuple&lt;Foo&gt;} 会通过,但{std::vector&lt;int&gt;, std::vector&lt;float&gt;, std::tuple&lt;Foo&gt;} 不会。

但是我得到了这个错误:

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 是如何未知的 - 谁能看到我做错了什么?

【问题讨论】:

  • 究竟什么是“非专业等价物”?我不明白你的例子{std::vector&lt;int&gt;, std::deque&lt;float&gt;, std::tuple&lt;Foo&gt;} vs {std::vector&lt;int&gt;, std::vector&lt;float&gt;, std::tuple&lt;Foo&gt;}
  • @m.s. std::vector&lt;int&gt;intstd::vector 上的特化,因此 std::vectorunspecialised 类型。该算法试图找到多个非专业类型(即它检查非专业的唯一性)。第一个示例通过,因为每个非专业类型都不同,而第二个示例失败,因为有两个 std::vectors。

标签: c++ boost boost-mp11


【解决方案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 不会得到它期望的谓词类型。恐怕我对这个库不太熟悉,无法告诉你如何获得除此之外的工作版本。

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 漂亮,谢谢!你能解释一下为什么我的方法不起作用吗?
    • StoryTeller 的回答解释了这一点,您可能应该接受它。您正在传递一个类型 (std::vector&lt;int&gt;),其中需要一个“类模板”(std::vector)。我已将is_specialisation_meta 更改为接受一个类型并从中推断出相应的“非专业类模板”。如果您传递的类型不是特化类型,您将收到另一个错误,并且您需要更改主模板的行为。
    • @llonesmiz 请接受 StoryTeller 作为建议的实际答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-07
    • 2019-03-21
    相关资源
    最近更新 更多