标签: c++-concepts

通过隐式转换小于运算符?

考虑以下课程:

struct C 
{
     /* Class contents, without any arithmetic operator... */
     constexpr operator int() noexcept; // Implicit conversion to int
};
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  • C是否可用于std::sort当前使用默认<运算符的标准算法?
  • C被认为是令人满意的LessThanComparable概念吗?
  • C是否满足假设的特定算法库的要求,该算法库需要类型LessThanComparable.

c++ implicit-conversion stl-algorithm c++-concepts c++17

16
推荐指数
1
解决办法
599
查看次数

身体是否需要阻止未评估的背景?

是概念定义的主体还是需要阻止未评估的上下文?例如.我可以std::declval安全使用吗?

template<typename T>
concept bool SomeConcept = requires(T a) {
    { a.someFunction(std::declval<int>()) } -> int;
};
Run Code Online (Sandbox Code Playgroud)

c++ c++-concepts

15
推荐指数
1
解决办法
216
查看次数

为什么概念细化不能使用简洁的语法

在完善概念时,在标准中始终如一地完成的方式是完全写出正在改进的概念.例如,在[concepts.integral]中,SignedIntegral精炼Integral如下:

template<class T>
  concept Integral = is_integral_v<T>;
template<class T>
  concept SignedIntegral = Integral<T> && is_signed_v<T>;
Run Code Online (Sandbox Code Playgroud)

为什么不能将精致的概念写成:

template<Integral T>
  concept SignedIntegral2 = is_signed_v<T>;
Run Code Online (Sandbox Code Playgroud)

SignedIntegral2似乎具有相同的明显含义SignedIntegral,但它甚至没有在clang上编译.是否有一个原因?

c++ c++-concepts c++20

15
推荐指数
1
解决办法
258
查看次数

C++20 概念:int not swappable_with int

我正在尝试 C++20 的概念,要么std::swappable_with是未定义的(Visual Studio,使用/std:c++latest),要么它的约束与下面的 MCVE 不匹配(g++10 使用-std=c++2a)——也就是说,int不能与int(!) . 有什么办法解决这个问题?如果int不能与 交换int,我看不到任何工作。

#include <concepts> 

template <typename T, typename U>
requires std::swappable_with<T,U>
void mySwap(T& t, U& u)
{
    T temp = t; t = u; u = temp;
}

int main()
{
    int x, y;
    mySwap(x, y);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

c++ c++-concepts c++20

15
推荐指数
2
解决办法
568
查看次数

检测范围大小的编译时常数

请注意,在提出此问题后,缺陷报告更改了下面提到的行为。见问题末尾。


编译器资源管理器链接

考虑以下:

// Variant 1

template<auto> struct require_constexpr;

template<typename R>
constexpr auto is_constexpr_size(R&& r) {
    return requires { typename require_constexpr<std::ranges::size(std::forward<R>(r))>; };
}

static_assert(!is_constexpr_size(std::vector{1,2,3,4}));
static_assert(is_constexpr_size(std::array{1,2,3,4}));
Run Code Online (Sandbox Code Playgroud)

这里的目标不是is_constexpr_size函数本身,而是找到一个 ( requires) 表达式,确定范围类型的大小是编译时常量,以便可以在按顺序通过转发引用获取任何范围的函数中使用它if constexpr基于它进行切换。

不幸的是,这不起作用,因为r它是引用类型并且不能在常量表达式中使用,尽管std::array调用std::range::sizes永远不会访问引用的对象。

变体 2:在函数参数中替换为 会改变这一点R&&R非引用类型变量的常量表达式要求较弱,MSVC 和 GCC 都接受经过此更改的代码,但 Clang 仍然不接受。我的理解是,目前有一项更改规则的提案,以便 with 的变体R&&也能按预期工作。

然而,在实现这一点之前,我正在寻找一种替代方案,不需要将参数限制为非引用类型。我也不想依赖于范围的类型,例如默认可构造的类型。因此我无法构造正确类型的临时对象。std::declval也无法使用,因为std::ranges::size需要评估。

我尝试了以下方法:

// Variant 3

return requires (std::remove_reference_t<R> s) { typename require_constexpr<std::ranges::size(std::forward<R>(s))>; };
Run Code Online (Sandbox Code Playgroud)

这被 MSVC 接受,但不被 …

c++ language-lawyer c++-concepts c++20 std-ranges

15
推荐指数
1
解决办法
903
查看次数

为什么选择模板模板函数重载而不是具有概念的模板?

以下代码在 static_assert 中失败:

#include <iostream>
#include <concepts>
#include <vector>

template <typename T>
concept container_type = requires(T& t) {
    typename T::value_type;
    typename T::reference;
    typename T::iterator;
    { t.begin() } -> std::same_as<typename T::iterator>;
    { t.end() } -> std::same_as<typename T::iterator>; 
};

// overload (0), fallback case
template <typename T>
constexpr int foo(const T& o) {
    return 0;
}

// overload (1), using the concept
constexpr int foo(const container_type auto& o) {
    return 1;
}

// overload (2), using template template parameter
template <typename T, …
Run Code Online (Sandbox Code Playgroud)

c++ c++-concepts c++20

14
推荐指数
1
解决办法
509
查看次数

为什么Sortable概念需要完全有序的值类型,而std :: sort只需要"小于"可比性?

关于概念N3701最新论文中,该sort算法有以下示例:

template<typename Cont>
  requires Sortable<Cont>()
void sort(Cont& cont)
Run Code Online (Sandbox Code Playgroud)

其中Sortable概念被定义为

template<typename T>
concept bool Sortable()
{
  return Permutable_container<T>() && Totally_ordered<Value_type<T>>();
}
Run Code Online (Sandbox Code Playgroud)

其中Totally_ordered,毫不奇怪,定义为

template<typename T>
constexpr bool Totally_ordered()
{
  return Weakly_ordered<T>() && Equality_comparable<T>();
}
Run Code Online (Sandbox Code Playgroud)

反过来Equality_comparable被定义为

template<typename T>
constexpr bool Equality_comparable()
{
  return requires(T a, T b) {
    {a == b} -> bool;
    {a != b} -> bool;
  };
}
Run Code Online (Sandbox Code Playgroud)

我没有找到定义Weakly_ordered,但我相信它应该是这样的(我是对的吗?)

template<typename T>
constexpr bool Weakly_ordered()
{
  return requires(T …
Run Code Online (Sandbox Code Playgroud)

c++ c++-concepts c++17

13
推荐指数
1
解决办法
693
查看次数

UB 在未评估的上下文中(例如需要表达式)仍然是 UB 吗?

C++ 20草案[concept.default.init] 没有精确定义default_initializable

template<class T>
concept default_initializable = constructible_from<T> &&
    requires { T{}; } &&
    is-default-initializable <T>; // exposition-only
Run Code Online (Sandbox Code Playgroud)

并用以下词语描述is-default-initializable应该做什么:

对于 type Tis-default-initializable <T> 为真当且仅当变量定义

T t;

对于某些发明的变量 t 是良构的;否则为假。访问检查就像在与 T 无关的上下文中执行。仅考虑变量初始化的直接上下文的有效性。

cppreference 上,我们找到了以下可能实现的建议:

template<class T>
concept default_initializable = constructible_from<T> &&
    requires { T{}; } &&
    is-default-initializable <T>; // exposition-only
Run Code Online (Sandbox Code Playgroud)

使用nullptr参数调用的placement-new 运算符会导致未定义的行为。

9)由标准的单对象放置 new 表达式调用。标准库实现不执行任何操作并返回未修改的 ptr。如果通过放置 new 表达式调用此函数并且 ptr 是空指针,则行为未定义。

我现在的问题是:建议的可能实现实际上有效吗?一方面我认为不,因为涉及一个表现出未定义行为的表达式。另一方面,我认为是的,因为这个表达式出现在未评估的上下文中,因此可能不需要具有明确定义的行为(?),只需要在语法上有效。但我无法为其中一个找到明确的证据。

第二个问题:如果事实证明后者是真的,那么为什么这种新的布局满足标准要求的T t;必须是良构的?对我来说,这看起来像是一个奇怪的黑客,因为简单和复合需求都没有提供T t;精确需求的可能性。但为什么这样做呢?

c++ undefined-behavior language-lawyer c++-concepts

13
推荐指数
1
解决办法
170
查看次数

如何将 C++20 约束的多个返回类型要求合并为一个返回类型要求?

目前,我已经使用 C++20约束和概念实现了分配器概念(指的是Boost 提案):

#include <concepts>
#include <iterator>

template <class A>
concept allocator =
  std::copy_constructible<A> &&
  std::equality_comparable<A> &&
  requires(A a) {
    { a.allocate(0) } -> std::regular;
    { a.allocate(0) } -> std::constructible_from<std::nullptr_t>;
    { a.allocate(0) } -> std::equality_comparable_with<std::nullptr_t>;
    { a.allocate(0) } -> std::random_access_iterator;
    { *a.allocate(0) } -> std::same_as<typename A::value_type&>;
  };
Run Code Online (Sandbox Code Playgroud)

您可以看到同一个函数有多个return-type-requirementallocate。有没有办法将它们组合成一个单一的返回类型要求,如下所示?

{ a.allocate(0) } -> std::regular &&
                     std::constructible_from<std::nullptr_t> &&
                     std::equality_comparable_with<std::nullptr_t> &&
                     std::random_access_iterator;
Run Code Online (Sandbox Code Playgroud)

c++ c++-concepts c++20

13
推荐指数
2
解决办法
817
查看次数

C++20 概念语法 - requires 参数变量是什么意思?

很多文章都给出了这样的例子:

template<typename T>
concept Equal = requires(T a, T b) {
    { a == b } -> std::same_as<bool>;
};
Run Code Online (Sandbox Code Playgroud)

如果我写:

template<typename T>
concept Equal = requires(T a) {
    { a == a } -> std::same_as<bool>;
};
Run Code Online (Sandbox Code Playgroud)

如果不是,为什么语法是这样设计的?为什么他们要我声明这些变量,如ab

为什么我需要多个相同类型的变量?为什么我什至需要变量?

template<typename T>
concept Equal = requires {
    { declval<const T&>() == declval<const T&>() }
        -> std::same_as<bool>;
};
Run Code Online (Sandbox Code Playgroud)

c++ c++-concepts c++20

13
推荐指数
1
解决办法
701
查看次数