【问题标题】:How to solve requires clause is incompatible如何解决requires子句不兼容
【发布时间】:2021-03-20 10:48:35
【问题描述】:

我正在尝试使用 C++20 概念实现递归版本 std::iter_value_t,以便可以检索像 std::vector<std::vector<...std::vector<T>...>> 这样的嵌套容器的基本类型 T。实验实现如下。

template<typename T>
concept is_iterable = requires(T x)
{
    *std::begin(x);
    std::end(x);
};

template<typename T> requires (!is_iterable<T>)
struct recursive_iter_value_t_detail
{
    typedef typename T type;
};

template<typename T> requires (is_iterable<T>)
struct recursive_iter_value_t_detail
{
    typedef typename std::iter_value_t<typename recursive_iter_value_t_detail<T>::type> type;
};

template<typename T>
using recursive_iter_value_t = typename recursive_iter_value_t_detail<T>::type;

尝试编译此代码后,弹出了唯一的错误消息'recursive_iter_value_t_detail': requires clause is incompatible with the declaration,我不确定requires clause is incompatible with the declaration 是什么意思。是模板结构不能这样重载的问题吗?请帮我解决这个问题。

recursive_iter_value_t&lt;std::vector&lt;std::vector&lt;int&gt;&gt;&gt; 的预期输出是int

【问题讨论】:

    标签: c++ templates recursion c++20 c++-concepts


    【解决方案1】:

    很多东西。

    首先,C++20 已经有了一个可迭代性的概念:称为std::ranges::range

    其次,从 C++11 开始,没有理由使用typedef。总是喜欢usingtypename 的使用也是无效的。所以using type = T; 而不是typedef typename T type; 这样做的原因是using 更强大(除了普通别名之外,您还可以使用别名模板)并且它是一种更理智的语法(您要介绍的名称在= 的左侧,而不是......基本上任何地方)。

    三、约束类模板偏特化的正确写法是主类是无约束的:

    template <typename T>
    struct recursive_iter_value_t_detail {
        using type = T;
    };
    

    而其他的 (a) 比主要的更受限制 并且 (b) 实际上必须是专业化(请参阅语法中额外的 &lt;T&gt;):

    template <typename T> requires std::ranges::range<T>
    struct recursive_iter_value_t_detail<T> {
        // ...
    };
    

    这也可以拼写:

    template <std::ranges::range T>
    struct recursive_iter_value_t_detail<T> {
        // ...
    };
    

    最后,你的递归步骤是倒退的。如果是范围,则需要首先解包,然后范围然后递归。您目前是第一次递归——但在同一类型上,所以这是无限递归。所以应该是:

    using type = recursive_iter_value_t_detail<std::iter_value_t<T>>::type;
    

    你可以写成更短的:

    template <std::ranges::range T>
    struct recursive_iter_value_t_detail<T>
        : recursive_iter_value_t_detail<std::iter_value_t<T>>
    { };
    

    总而言之[demo]:

    template<typename T>
    struct recursive_iter_value_t_detail
    {
        using type = T;
    };
    
    template <std::ranges::range T>
    struct recursive_iter_value_t_detail<T>
        : recursive_iter_value_t_detail<std::iter_value_t<T>>
    { };
    
    template<typename T>
    using recursive_iter_value_t = typename recursive_iter_value_t_detail<T>::type;
    

    【讨论】:

    • 你应该说为什么 typename在这里无效(没有资格)。
    猜你喜欢
    • 2013-05-26
    • 1970-01-01
    • 2021-11-16
    • 2021-06-24
    • 1970-01-01
    • 2021-06-17
    • 1970-01-01
    • 1970-01-01
    • 2014-05-28
    相关资源
    最近更新 更多