简体   繁体   English

禁用带有概念的非模板化方法

[英]Disable non-templated methods with concepts

Is there a syntax to constraint a non-templated method?是否有约束非模板化方法的语法? All the syntaxes I've tried on godbolt with clang concepts branch and gcc fail to compile:我用 clang 概念分支和 gcc 在 Godbolt 上尝试的所有语法都无法编译:

// these examples do not compile

template <bool B>
struct X
{
    requires B
    void foo() {}
};

template <class T>
struct Y
{
    requires (std::is_trivially_copyable_v<T>)
    auto foo() {}
};

The trick to make it compile is the same trick you needed to do with SFINAE, make the methods template, even though they really are not templates.使其编译的技巧与您对 SFINAE 所需的技巧相同,制作方法模板,即使它们实际上不是模板。 And funny enough, the constraint doesn't seem to need the method template, it can work fine on the class template alone, so I really hope there is a way to apply the constraints with concepts without having to resort to the old hacks:有趣的是,约束似乎不需要方法模板,它可以单独在 class 模板上正常工作,所以我真的希望有一种方法可以将约束与概念一起应用,而不必求助于旧技巧:

// old hacks

template <bool B>
struct X
{
    template <bool = B>
    requires B
    auto foo() {}
};

template <class T>
struct Y
{
    template <class = T>
    requires std::is_trivially_copyable_v<T>
    auto foo() {}
};

Real life example:现实生活中的例子:

template <class T, bool Copyable_buf = false>
struct Buffer
{
    /* ... */

    requires Copyable_buf
    Buffer(const Buffer& other)  {}

    /* ... */
};

template <class T>
using Copyable_buffer = Buffer<T, true>;

To support the other answer on this, here is the normative wording about this, from the latest standard draft:为了支持对此的其他答案,这是来自最新标准草案的规范性措辞:

[dcl.decl] [dcl.decl]

1 A declarator declares a single variable, function, or type, within a declaration. 1声明器在声明中声明单个变量 function 或类型。 The init-declarator-list appearing in a declaration is a comma-separated sequence of declarators, each of which can have an initializer.出现在声明中的 init-declarator-list 是一个以逗号分隔的声明符序列,每个声明符都可以有一个初始化器。

 init-declarator-list: init-declarator init-declarator-list, init-declarator init-declarator: declarator initializer opt declarator requires-clause init-declarator-list: init-declarator init-declarator-list, init-declarator init-declarator: declarator 初始化器opt declarator requires-clause

4 The optional requires-clause ([temp]) in an init-declarator or member-declarator shall not be present when the declarator does not declare a function ([dcl.fct]). 4当声明器未声明 function ([dcl.fct]) 时,init-declarator 或 member-declarator 中的可选 requires-clause ([temp]) 不应出现。 When present after a declarator, the requires-clause is called the trailing requires-clause.当出现在声明符之后时,要求子句称为尾随要求子句。 The trailing requires-clause introduces the constraint-expression that results from interpreting its constraint-logical-or-expression as a constraint-expression.尾随的 requires 子句引入了将其约束逻辑或表达式解释为约束表达式而产生的约束表达式。 [ Example: [ 例子:

 void f1(int a) requires true; // OK auto f2(int a) -> bool requires true; // OK auto f3(int a) requires true -> bool; // error: requires-clause precedes trailing-return-type void (*pf)() requires true; // error: constraint on a variable void g(int (*)() requires true); // error: constraint on a parameter-declaration auto* p = new void(*)(char) requires true; // error: not a function declaration

— end example ] —结束示例]

As those two paragraphs specify, a trailing requires clause can appear at the end of function declarators.正如这两段所指定的,结尾的 requires 子句可以出现在 function 声明符的末尾。 Its meaning is to constrain the function by the constant expression it accepts as an argument (which includes concepts).它的含义是通过它接受作为参数(包括概念)的常量表达式来约束 function。

Yes, there is!!就在这里!! The requires clause can appear as the last element of a function declarator, in which case it allows to constraint non-templated methods (or free functions for that matter): requires 子句可以作为 function 声明符的最后一个元素出现,在这种情况下,它允许约束非模板化方法(或就此而言的自由函数):

// This works as expected! Yey!!

template <class T, bool Copyable_buf = false>
struct Buffer
{
    Buffer(const Buffer& other) requires Copyable_buf
    {
        // ...
    }
};

template <bool B>
struct X
{
    auto foo() requires B
    {
        // ...
    }
};

template <class T>
struct Y
{
    auto foo() requires std::is_trivially_copyable_v<T>
    {
        // ...
    }
};

This answer is empirical, based on testing on current implementations of concepts.这个答案是经验性的,基于对当前概念实现的测试。 Godbolt test .天马行空测试 Storry Tellers's answer gives standard quotes confirming this behavior.故事出纳员的回答给出了证实这种行为的标准报价。

There was a change regarding this recently.最近这方面发生了变化。 See https://github.com/cplusplus/nbballot/issues/374https://github.com/cplusplus/nbballot/issues/374

It states:它指出:

How constraints work with non-templated functions is still under heavy construction during this late stage in the process.在此过程的后期阶段,约束如何与非模板化函数一起工作仍在繁重的建设中。 While we have provided various comments that build in a direction where supporting such constructs (including ordering between multiple constrained functions based on their constraints) would become possible, we acknowledge that WG 21 might not find a solution with consensus in time for the DIS.尽管我们提供了各种意见,这些意见旨在支持此类结构(包括基于约束在多个受约束函数之间进行排序)成为可能,但我们承认 WG 21 可能无法及时为 DIS 找到达成共识的解决方案。 We ask WG 21 to evaluate the risk of shipping the feature in such a state and consider removing the ability to declare such functions.我们要求 WG 21 评估在此类 state 中发布该功能的风险,并考虑取消声明此类功能的能力。

Does EWG want to consider this for C++20? EWG 是否想为 C++20 考虑这个?

 | F | A | |----|----| | 16 | 0 |

Motion passes.议案通过。 Hubert to coordinate with CWG. Hubert 与 CWG 进行协调。

Emphasis mine.强调我的。

So it appears that constrained non-templated functions were removed from C++20 as of right now.因此,目前看来,受约束的非模板函数已从 C++20 中删除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM