标签: c++20

重写的比较运算符会导致哪些重大变化?

在 C++20 中有一些关于重写比较运算符的新规则,我试图了解它们是如何工作的。我遇到了以下程序

struct B {};

struct A
{
    bool operator==(B const&);  // #1
};

bool operator==(B const&, A const&);  // #2

int main()
{
  B{} == A{};  // C++17: calls #2
               // C++20: calls #1
}
Run Code Online (Sandbox Code Playgroud)

这实际上破坏了现有的代码。我对此感到有些惊讶;#2实际上对我来说仍然看起来更好:p

那么这些新规则如何改变现有代码的含义呢?

c++ comparison-operators language-lawyer c++20

43
推荐指数
2
解决办法
2247
查看次数

使用 C++20 三路比较进行更多无声行为改变

令我惊讶的是,我遇到了另一个障碍,例如C++20 行为用相等运算符破坏了现有代码?.

考虑一个简单的不区分大小写的键类型,用于例如std::setor std::map

// Represents case insensitive keys
struct CiKey : std::string {
    using std::string::string;
    using std::string::operator=;

    bool operator<(CiKey const& other) const {
        return boost::ilexicographical_compare(*this, other);
    }
};
Run Code Online (Sandbox Code Playgroud)

简单的测试:

using KeySet   = std::set<CiKey>;
using Mapping  = std::pair<CiKey, int>; // Same with std::tuple
using Mappings = std::set<Mapping>;

int main()
{
    KeySet keys { "one", "two", "ONE", "three" };
    Mappings mappings {
        { "one", 1 }, { "two", 2 }, { "ONE", 1 }, { "three", …
Run Code Online (Sandbox Code Playgroud)

c++ spaceship-operator stdtuple c++17 c++20

43
推荐指数
2
解决办法
2549
查看次数

没有为C ++ 20中的自定义太空船运算符实现定义等式运算符

<=>在C ++ 20中使用新的宇宙飞船运算符遇到一种奇怪的行为。我正在将Visual Studio 2019编译器与一起使用/std:c++latest

这段代码可以正常编译:

#include <compare>

struct X
{
    int Dummy = 0;
    auto operator<=>(const X&) const = default; // Default implementation
};

int main()
{
    X a, b;

    a == b; // OK!

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

但是,如果我将X更改为:

struct X
{
    int Dummy = 0;
    auto operator<=>(const X& other) const
    {
        return Dummy <=> other.Dummy;
    }
};
Run Code Online (Sandbox Code Playgroud)

我收到以下编译器错误:

error C2676: binary '==': 'X' does not define this operator or a conversion to …

c++ spaceship-operator c++20

42
推荐指数
3
解决办法
2365
查看次数

为什么 C++20 的 `std::popcount` 仅限于无符号类型?

P0553R4中的功能:位运算仅限于无符号整数。该提案没有给出这一限制的理由。我可以看到,如果没有定义有符号整数的位表示,这是有意义的,但使用 C++20,我们可以保证有符号整数使用二进制补码。

对我来说,允许使用有符号整数类型调用eg似乎是合理的std::popcount,因为实现可以简单地转换为相应的无符号类型以在无符号域中执行位操作。

P0553R4添加这个约束的原因是什么?(只是 P0553R4 和 P0907R4 之间缺少同步吗?)

c++ language-design language-lawyer c++20

41
推荐指数
2
解决办法
4990
查看次数

新的迭代器要求

我注意到大多数(如果不是所有)容器现在都需要它们的::iterator类型LegacySomethingIterator而不是SomethingIterator.

例如,std::vector<>::iterator 现在需要:

iterator LegacyRandomAccessIterator

这似乎是大多数其它容器一样,都是需要自己迭代器从去SomethingIteratorLegacySomethingIterator.

还有"新"要求采用旧要求的名称,例如RandomAccessIterator,为什么这些要求被添加?在我看来,新的变种只会影响遗留的变种,没有差异.

为什么首先创建新的,他们的要求对我来说是一样的.为什么新的只是替换旧的要求而不是现在有两个不同的名称(例如RandomAccessIteratorLegacyRandomAccessIterator)?

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

40
推荐指数
1
解决办法
3570
查看次数

未评估上下文中的默认模板参数和lambda:错误或功能?

我们考虑使用完全相同的语法创建两种不同类型的目标。这可以通过lambdas轻松完成:

auto x = []{};
auto y = []{};
static_assert(!std::is_same_v<decltype(x), decltype(y)>);
Run Code Online (Sandbox Code Playgroud)

但是,我们正在寻找另一种更优雅的语法,而不是使用lambda。这是一些测试。我们首先定义一些工具:

#include <iostream>
#include <type_traits>
#define macro object<decltype([]{})>
#define singleton object<decltype([]{})>

constexpr auto function() noexcept
{
    return []{};
}

template <class T = decltype([]{})>
constexpr auto defaulted(T arg = {}) noexcept
{
    return arg;
}

template <class T = decltype([]{})>
struct object
{
    constexpr object() noexcept {}
};

template <class T>
struct ctad
{
    template <class... Args>
    constexpr ctad(const Args&...) noexcept {}
};

template <class... Args>
ctad(const Args&...) -> …
Run Code Online (Sandbox Code Playgroud)

c++ lambda language-lawyer template-meta-programming c++20

39
推荐指数
1
解决办法
758
查看次数

常数整数和常数求值

考虑以下程序:

#include <iostream>
#include <type_traits>

constexpr int f() {
  if (std::is_constant_evaluated())
    return -1;
  else return 1;
}

int main() {
  int const i = f();
  std::cout << i;
}
Run Code Online (Sandbox Code Playgroud)

打印-1在运行时(wandbox)。

但是,如果我throw在编译时求值时使用该函数:

#include <iostream>
#include <type_traits>

constexpr int f() {
  if (std::is_constant_evaluated())
    throw -1; // <----------------------- Changed line
  else return 1;
}

int main() {
  int const i = f();
  std::cout << i;
}
Run Code Online (Sandbox Code Playgroud)

它可以编译并输出1(wandbox)。为什么我没有出现编译失败?

c++ constexpr c++20

38
推荐指数
1
解决办法
629
查看次数

C++20 范围太多 | 运营商?

我正在为此代码使用 g++ 10.2。没有任何人知道为什么我得到一个编译错误在过去std::views::reverseresults3

#include <vector>
#include <ranges>

int main() {
    auto values = std::vector{1,2,3,4,5,6,7,8,9,10};
    auto even = [](const auto value) {
        return value % 2 == 0;
    };
    auto square = [](const auto value) {
        return value * value;
    };

    auto results1 = values
        | std::views::filter(even)
        | std::views::reverse
        | std::views::take(4)
        | std::views::reverse;

    auto results2 = values
        | std::views::transform(square)
        | std::views::reverse
        | std::views::take(4)
        | std::views::reverse;

    auto results3 = values
        | std::views::filter(even)
        | std::views::transform(square)
        | std::views::reverse
        | std::views::take(4) …
Run Code Online (Sandbox Code Playgroud)

c++ compiler-errors c++20 std-ranges

38
推荐指数
2
解决办法
2900
查看次数

constexpr 上下文中带有 consteval 构造函数的新表达式

struct A {       
    consteval A() {};
};

constexpr bool g() {
    auto a = new A;
    delete a;
    return true;
}

int main() {
    static_assert(g());
}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/jsq35WxKs

GCC 和 MSVC 拒绝该程序,ICC 和 Clang 接受它:

///MSVC: 
<source>(6): error C7595: 'A::A': call to immediate function is not a constant expression
Compiler returned: 2

//GCC:
<source>: In function 'constexpr bool g()':
<source>:6:18: error: the value of '<anonymous>' is not usable in a constant expression
    6 |     auto a = new A;
      |                  ^ …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer constexpr c++20 consteval

35
推荐指数
1
解决办法
1244
查看次数

运算符 == 和运算符 != 的存在打破了一些概念

升级到最新的 Visual Studio 2022 版本 17.6 后,我们的自定义视图之一停止被识别为std::ranges::range. 事实证明,问题出在视图的迭代器中operator ==operator !=

请找到下面的最小简化示例(已经没有视图和迭代器):

struct A {
    friend bool operator ==( const A &, const A & ) = default;
};

struct B {
    friend bool operator ==( const B &, const B & ) = default;
    friend bool operator ==( const B &, const A & ) { return false; }
    // Visual Studio 2022 version 17.6 does not like next line
    friend bool operator !=( const …
Run Code Online (Sandbox Code Playgroud)

c++ comparison-operators language-lawyer c++-concepts c++20

35
推荐指数
2
解决办法
4505
查看次数