首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C++概念-需求括号中的概念导致两个相互冲突的错误消息

C++概念-需求括号中的概念导致两个相互冲突的错误消息
EN

Stack Overflow用户
提问于 2020-05-28 09:47:43
回答 1查看 505关注 0票数 3

今天早上,为了更好地理解概念,我努力工作(仍然是个新手),我偶然发现了一些奇怪的东西。

我想了解如何好的概念与Lambda函数工作,我试着玩了很多。

让我们从下面的代码开始(这很有效!):

代码语言:javascript
运行
复制
#include <concepts>
#include <stdio.h>

template <typename T>
concept Integral =
requires(T n)
{
    { n } -> std::convertible_to<int>;
};

template <typename Operation>
concept CalculatorOperation =
requires(Operation&& op, int a, int b)
{
    { op(a, b) } -> Integral;
};

template <CalculatorOperation Operation>
static inline constexpr Integral auto Calculator(const Integral auto First,
                                                 const Integral auto Second)
{
    return Operation{}(First, Second);
}

int main()
{
    static constexpr auto Multiply = [](const Integral auto First,
                                        const Integral auto Second)
                       { return First * Second; };
    return Calculator<decltype(Multiply)>(15, 18);
}

我创建了一个完整的概念,如果一个类型可以转换为int,那么这个概念(只是为了虚拟的缘故)是令人满意的。我已经创建了一个计算器操作概念,它接受一个lambda,两个int,并确保该操作返回一个整数。

我决定让这个概念中的int变成一个积分,因为我不想只接受int的操作(我想要所有的整数类型)。

所以我改变了

代码语言:javascript
运行
复制
requires(Operation&& op, int a, int b)

代码语言:javascript
运行
复制
requires(Operation&& op, Integral&& a, Integral&& b)

这不仅对我没用,实际上我收到了两条相互矛盾的错误信息(关于GCC 10.1):

代码语言:javascript
运行
复制
<source>:13:30: error: placeholder type not allowed in this context


<source>:13:30: error: expected 'auto' or 'decltype(auto)' after 'Integral'

   13 |     requires(Operation&& op, Integral&& a, Integral&& b)

我是在哥德波特的网站编译器资源管理器上运行的。这是怎么回事?有真正的办法吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-05-28 11:37:03

首先,通过这样做:

代码语言:javascript
运行
复制
requires(Operation&& op, Integral&& a, Integral&& b)

你的意思可能是:

代码语言:javascript
运行
复制
requires(Operation op, Integral auto a, Integral auto b)

也就是说,使用占位符类型说明符的类型约束auto形式。

但是,auto参数会生成函数模板,而auto占位符相当于该函数模板的实际类型模板参数,因此它只能出现在从初始化程序中进行类型推断的上下文中,这意味着:

代码语言:javascript
运行
复制
void foo(auto x);

相当于:

代码语言:javascript
运行
复制
template <typename T>
void foo(T x);

类似地,

代码语言:javascript
运行
复制
void bar(Integral auto x);

相当于:

代码语言:javascript
运行
复制
template <Integral T>
void bar(T x);

这种转换不适用于需求表达式,即没有可以推导其类型的初始化程序,因此不能在需求参数列表的参数声明中使用auto占位符。正如标准所说,这些参数“仅用作定义需求的表示法”。因此,您需要显式地指定概念工作所需的所有模板参数,例如:

代码语言:javascript
运行
复制
template <typename Operation, typename Lhs, typename Rhs>
concept CalculatorOperation = requires(Operation op, Lhs a, Rhs b)
{
    { op(a, b) } -> Integral;
};

template <typename Operation>
constexpr Integral auto Calculator(Integral auto first, Integral auto second)
    requires CalculatorOperation<Operation, decltype(first), decltype(second)>
{
    return Operation{}(first, second);
}

还请注意,我从需求参数列表中的每个参数声明中删除了&&。整个requires表达式是一个未计算的上下文,实际上没有传递任何参数。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62061706

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档