如何解决requires子句不兼容

我正在尝试std::iter_value_t使用 C++20 概念实现递归版本,以便可以检索T类似嵌套容器的基本类型std::vector<std::vector<...std::vector<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意思。是不是template struct 不能像这样重载的问题?请帮我解决这个问题。

的预期输出recursive_iter_value_t<std::vector<std::vector<int>>>int

回答

很多东西。

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

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

第三,正确编写受约束的类模板偏特化的方法是primary是无约束的:

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

其他的(a)主要的更受限制,(b)实际上必须是专业化(请参阅<T>语法中的额外内容):

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

总而言之[演示]:

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;


以上是如何解决requires子句不兼容的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>