考虑这个代码:
struct A
{
template <typename T>
concept foo = true;
};
Run Code Online (Sandbox Code Playgroud)
它不编译。我的 Clang 10 给了我error: concept declarations may only appear in global or namespace scope,GCC 说了类似的话。
有理由不允许吗?我不明白为什么它不能工作,即使封闭类是一个模板。
如何使用 C++20 概念限制可变参数模板和折叠表达式中允许的类型?
例如,假设我想限制以下折叠表达式仅支持整数类型,我该怎么做?
#include <string>
#include <iostream>
#include <concepts>
using namespace std;
template<typename... Args> // requires (is_integral<Args>::value )
int sum(Args... args) { return (... + args); }
int main()
{
cout << sum(1,2,3);
}
Run Code Online (Sandbox Code Playgroud) 概念(即最近从C++ 0x标准中删除的那些)与Java等语言中的接口有何不同?
我已经听说所有这些关于C++ 0x的新的(on /.)不再有概念,但我不知道它们是什么?有人可以向我解释一下吗?
Bjarne Stroustrup最近发表了一篇关于C++ Concepts 的报告,他提到了一些让我感到惊讶的事情.示例(在第7.1节中)使用"简写模板表示法",基本上是这样的:
void foo1(auto x,auto y); // x and y may have different types (1)
void foo2(SomeConcept x,SomeConcept y); // x and y must have the same type (2)
Run Code Online (Sandbox Code Playgroud)
就我个人而言,这似乎非常违反直觉; 事实上,我希望foo2接受不同类型的值x,y,只要各个类型满足SomeConcept.请注意,程序员始终可以通过编写以下内容之一来明确指定其意图:
template <SomeConcept T> void foo2(T x, T y); // (3)
template <SomeConcept T1,SomeConcept T2> void foo2(T1 x,T2 y); // (4)
Run Code Online (Sandbox Code Playgroud)
直觉上,我希望(2)中的简写符号等同于(4),因此更符合无约束模板(1)的含义.有人可以解释这个问题并解释这个设计决定背后的理由吗?
一些评论:
我正在阅读Constraints上的cppreference页面并注意到这个例子:
// example constraint from the standard library (ranges TS)
template <class T, class U = T>
concept bool Swappable = requires(T t, U u) {
swap(std::forward<T>(t), std::forward<U>(u));
swap(std::forward<U>(u), std::forward<T>(t));
};
Run Code Online (Sandbox Code Playgroud)
我很困惑他们为什么要用std::forward.有些人试图在模板参数中支持引用类型吗?我们不想swap用forward左值调用,并且当标量(非参考)类型时T,表达式不是rvalues U吗?
例如,我希望这个程序在Swappable实现时失败:
#include <utility>
// example constraint from the standard library (ranges TS)
template <class T, class U = T>
concept bool Swappable = requires(T t, U u) {
swap(std::forward<T>(t), std::forward<U>(u));
swap(std::forward<U>(u), std::forward<T>(t)); …Run Code Online (Sandbox Code Playgroud) 我在完全从任何模板中删除的上下文中玩弄 C++ 概念和函数重载,并偶然发现了这一点:
struct S
{
int mult(int x) requires (true) { return x; }
int mult(int x) requires (false) { return x * 2; }
};
int main()
{
std::cout << S{}.mult(5) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
g++ 11 拒绝编译此代码段,因为requires-clauses 可能不会附加到非模板函数。
然而,clang++ 13 对这个代码段很好,但令人惊讶的是它吐出10而不是5我所期望的。
我知道 C++20 标准最近才出炉,所以我完全理解关于概念有很多问题需要解决。
忽略常量字面概念的明显无用,我的问题是:带有 -requires子句的程序是否总是格式错误的false,可能不需要诊断?或者,也许,正如 g++ 所说,我什至根本没有合法的 C++?
概念非常擅长将错误定位到“不满足约束”的代码行。
但是,我想知道是否可以在那里发布自定义信息消息。static_assert 的好处就是这种可能性。用例:任何想要帮助用户找出某个表达式不满足约束的原因的库。
这是一个简单的例子,只是为了有一些代码。您可能会争辩说,任何体面的“用户”都必须能够弄清楚编译器的注释“因为 'is_base_of<Base, C>' 评估为 false”,但更多的自定义信息不会受到伤害。肯定会有更复杂的概念。
template<typename B, typename D>
concept is_base_of = std::is_base_of_v<B, D>;
template <typename T, is_base_of<T> BaseType>
struct BaseWrapper { };
int main()
{
class Base {};
class Derived : public Base {};
class C {};
using T1 = BaseWrapper<Derived,Base>;
using T2 = BaseWrapper<C,Base>; // fails right here, but a custom message would be nice
}
Run Code Online (Sandbox Code Playgroud) 可以肯定的是c++20,根据即将到来的标准,根据最近的科隆ISO C ++会议的一份Reddit报告,我们将能够指定模板的概念,并且对于每个类/功能模板,我们将能够设置其类型的约束。 。但是,在文档和教程中(例如here),我找不到适用于多类型用例的正确语法。
假设我们有一个多类型的概念:
template<typename T1, typename T2>
concept AreEqComparable = requires(T1 a, T2 b) {
{ a == b } -> bool;
};
Run Code Online (Sandbox Code Playgroud)
假设我想在两个不同类型之间定义一个简单的比较函数。我怎样才能做到这一点?更具体地说,我应该在???下面的代码部分中写什么:
???
bool are_equal(T1 a, T2 b) { return a == b; }
Run Code Online (Sandbox Code Playgroud)
我在这里,这里,甚至这里都没有找到关于这个案例的参考。我已经随机尝试过类似的东西:
/* 1 */ template<AreEqComparable T1, T2>
/* 2 */ AreEqComparable<T1, T2>
/* 3 */ template<AreEqComparable<T1, T2>>
Run Code Online (Sandbox Code Playgroud)
但是所有这些都引发语法错误。我认为答案应该在Bjarne Stroustrup的规范 …
该概念equality_comparable_with<T, U>旨在声明类型T和 的对象U可以相互比较,如果它们是,则这具有预期的含义。没关系。
但是,这个概念也需要common_reference_t<T&, U&>存在。其主要推动力common_reference及其伴随的功能似乎是启用代理迭代器,有一个地方来表示此类迭代器之间的关系reference以及value_type此类迭代器的关系。
太好了,但是……这与测试 aT和 a 是否U可以相等有什么关系?为什么标准要求这样做T并且U有一个共同的参考关系只是为了让你比较它们相等?
这会产生奇怪的情况,其中很难有两种类型没有合理地具有逻辑可比性的公共引用关系。例如,vector<int>和pmr::vector<int>逻辑上应该是可比的。但它们不可能,因为这两种不相关的类型之间没有合理的公共引用。