如何在C ++ 20'requires'表达式中使用未指定的类型?

问题描述

我试图写一个C ++ 20概念来表达一个类型必须具有某种接受参数的方法的要求,但是出于这个概念的目的,我不在乎参数类型是什么。

我试图写类似的东西:

template <typename T>
concept HasFooMethod = requires(T t,auto x)
{
    { t.Foo(x) } -> std::same_as<void>;
};

但是,gcc和clang都拒绝了此操作,从而给出了这样的错误,即'auto'不能用这种方式在require的参数列表中使用。

另一种选择是将“ x”的类型作为第二个模板参数:

template <typename T,typename TX>
concept HasFooMethod = requires(T t,TX x)
{
    { t.Foo(x) } -> std::same_as<void>;
};

但是,这要求在使用概念时必须明确指定TX,无法推论得出:

struct S { void Foo(int); };
static_assert(HasFooMethod<S>);         // doesn't compile
static_assert(HasFooMethod<S,int>);    // the 'int' must be specified

有什么办法写出允许Foo接受 unspecified 类型的参数的概念?

问题Concept definition requiring a constrained template member function非常相似,但又不同:该问题询问如何要求(模板化的)方法可以采用满足给定概念的 any 类型。关于要求一种方法采用 some 特定类型,尽管该类型未指定。在量词方面,另一个问题是关于(有界的)普遍量化的问题,而这又是关于存在性量化的问题。另一个问题的答案也不适用于我的情况。

解决方法

概念并不旨在提供您正在寻找的功能。 So they don't provide it.

概念旨在限制模板,以指定模板在其定义中打算使用(或至少可以自由使用)的一组表达式或语句。

在您如此受限制的模板中,如果您编写表达式t.Foo(x),则知道x的类型。它可以是具体类型,模板参数或从模板参数派生的名称。无论哪种方式,x的类型在受约束的模板上都是可用的。

因此,如果要限制这样的模板,请同时使用tx的类型。那时您都可以使用这两种功能,因此创建这样的约束没有问题。也就是说,约束不是作为隔离类型放在T上的;它位于TX之间。

概念并不是在真空中工作的,它与约束的实际使用位置没有任何关联。您不应该专注于创建一元概念,以便用户可以static_assert针对他们的类。概念并不用于测试类型是否满足它们(这基本上就是您的static_assert所做的事情);它们旨在约束使用的模板定义。

您的约束必须为FooCallableWith,而不是HasFooMethod

,

可以通过定义一个可以隐式转换为(几乎)任何东西的适配器类型来实现与此接近的事情:

struct anything
{
    // having both these conversions allows Foo's argument to be either
    // a value,an lvalue reference,or an rvalue reference

    template <typename T>
    operator T&();

    template <typename T>
    operator T&&();
};

请注意,这些运算符不需要实现,因为它们只会在未评估的上下文中使用(实际上,不能对所有类型T都实现它们)。

然后,HasFooMethod可以写为:

template <typename T>
concept HasFooMethod = requires(T t,anything a)
{
    { t.Foo(a) } -> std::same_as<void>;
};

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...