【问题标题】:Why doesn't my example satisfy this "requires" expression?为什么我的示例不满足这个“要求”表达式?
【发布时间】:2021-06-18 08:10:58
【问题描述】:

我正在尝试将概念与可变参数模板一起使用。我的模板类在下面。这个概念应该说:“每个T 类型都应该有一个成员函数Func,它接受FuncArgType 类型的输入。

#pragma once

#include <tuple>
#include <concepts>
#include <iostream>

template<typename FuncArgType, typename... Ts>
requires requires
(FuncArgType func_arg, std::tuple<Ts...> args) {
    std::apply([&func_arg](auto&... ts) {(ts.Func(func_arg), ...); }, args);
}
class MyClass
{
public:
    MyClass() {}
};

在我看来这是正确的,尽管我使用 std::apply 时可能会出错。然后我尝试使用MyClass 创建一个对象。我定义了两个类AB 作为我的TsFuncArgTypeint

class A {
public:
    A() {}
    void Func(int i) {
        std::cout << "Called Func of A";
    }

};


class B {
public:
    B() {}
    void Func(int i) {
        std::cout << "Called Func of B";
    }

};

我现在尝试创建MyClass 的实例。

#include "MyClass.h"

int main() {
    MyClass<int, A, B> my_class{}; // constraints not satisfied

    return 0;
}

错误信息是

Source.cpp(4,19): error C7602: 'MyClass': the associated constraints are not satisfied

(还有其他几条错误消息,但基本上都说my_class 无效。)

为什么AB 不满足我的约束条件?我的约束是否说出了我想要它说的内容?如何让我的约束说出上面的粗体声明?

【问题讨论】:

  • 您使用的是哪个编译器?我已经尝试过 clang 和 gcc,模板已经给了我一个错误,没有其他的。
  • Microsoft Visual C++20
  • 查看 Godbolt 中的其他错误消息后,我认为错误在于在 requires expression 中使用 lambda 捕获。 Lambdas、std::applyrequires 对我来说仍然是新事物,所以我还在摸索中。 “错误:约束变量 'func_arg' 不能在评估的上下文中使用”
  • 你可以试试std::apply([](auto&amp;... ts) {FuncArgType i; (ts.Func(i), ...); }, args) ?? t=requires 子句中的参数实际上不是变量。如果可以的话,我会回答的
  • @nhatnq 没用。我收到以下错误,我之前也遇到过“Source.cpp(4,21): error C2146: syntax error: missing ';'在标识符 'myclass' 之前", "'MyClass': 非法将此类型用作表达式", "'myclass': 未声明的标识符"。

标签: c++ compiler-errors apply variadic-templates c++-concepts


【解决方案1】:

您不需要 lambda 或 std::apply。您可以直接使用参数包:

template<typename FuncArgType, typename... Ts>
requires requires(FuncArgType func_arg, Ts... args) 
{
    (args.Func(func_arg), ...);
}

请注意,这允许隐式转换。

Here 是一个完整的例子。

但是,您的概念是正确的。 C++20 中有一个变化,允许在未评估的上下文中捕获 lambda。有关更多详细信息,请参阅this 答案。如果您更新编译器,您的概念应该是有效的。最新的 VS 预览版 (16.11) 支持此更改(尽管智能感知仍将其显示为错误)。

【讨论】:

  • 它在eel.is/c++draft/expr.prim.req.general#nt:requires-expression 中声明。 需求表达式可能会引入局部参数
  • @nhatnq 上面的段落说:“出现在需求主体中的表达式是未评估的操作数。” 过去,在未评估的上下文中禁止使用 lambda。我在当前标准中找不到任何关于 lambda 限制的内容,这就是为什么我请人做语言律师
猜你喜欢
  • 2020-11-13
  • 1970-01-01
  • 2012-06-20
  • 2012-04-29
  • 1970-01-01
  • 1970-01-01
  • 2011-07-24
  • 2023-01-25
  • 2021-04-21
相关资源
最近更新 更多