小编康桓瑋*_*康桓瑋的帖子

std::visit 相对于 if-else 的优势

我发现 std::visit 可以按以下方式使用:

    std::visit([](auto&& arg) {
        using T = std::decay_t<decltype(arg)>;
        if constexpr (std::is_same_v<T, int>)
            std::cout << "int with value " << arg << '\n';
        else if constexpr (std::is_same_v<T, std::string>)
            std::cout << "std::string with value " << std::quoted(arg) << '\n';
        else 
            static_assert(always_false_v<T>, "non-exhaustive visitor!");
    }, v);
Run Code Online (Sandbox Code Playgroud)

但相反,我想我也可以使用

    if(auto x = std::get_if<int>(&v))
        std::cout << " is int " << *x << std::endl;
    else if(auto x = std::get_if<std::string>(&v))
        std::cout << " is String " << *x << std::endl;
    else
        std::cout << "non-exhaustive visitor!" …
Run Code Online (Sandbox Code Playgroud)

c++ variant c++17

8
推荐指数
1
解决办法
2418
查看次数

C++20 的奇怪返回值需要表达式

考虑需要表达式

constexpr auto b = requires { []{}; };
Run Code Online (Sandbox Code Playgroud)

GCC通过以下两个static_assert

 static_assert(b);
 static_assert(!b); 
Run Code Online (Sandbox Code Playgroud)

这看起来非常奇怪。我希望 的值b应该是true。这只是一个 GCC 错误吗?

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

7
推荐指数
1
解决办法
166
查看次数

三路运算符 &lt;=&gt; 返回带有隐式转换函数的结构体

考虑以下无用的代码:

struct S{
  constexpr operator int() const { return 0; }
  constexpr auto operator<=>(S) const { return *this; }
};

static_assert(S{} <= S{});
Run Code Online (Sandbox Code Playgroud)

Clang 和 MSVC 接受此代码,但 GCC拒绝它并显示错误消息:

error: no match for 'operator<=' (operand types are 'S' and 'int')
Run Code Online (Sandbox Code Playgroud)

哪个编译器是对的?是怎么operator<=合成的operator<=>

c++ language-lawyer implicit-conversion spaceship-operator c++20

7
推荐指数
1
解决办法
165
查看次数

为什么view_interface::data const 重载需要额外检查const D 是否满足ranges::range?

根据[view.interface],非常量和常量重载data函数定义如下:

template<class D>
  requires is_class_v<D> && same_­as<D, remove_cv_t<D>>
class view_interface : public view_base {
private:
  constexpr D& derived() noexcept {                   // exposition only
    return static_cast<D&>(*this);
  }
  constexpr const D& derived() const noexcept {       // exposition only
    return static_cast<const D&>(*this);
  }
public:
  constexpr auto data() requires contiguous_­iterator<iterator_t<D>> {
    return to_address(ranges::begin(derived()));
  }
  constexpr auto data() const
    requires range<const D> && contiguous_­iterator<iterator_t<const D>> {
      return to_address(ranges::begin(derived()));
    }
};
Run Code Online (Sandbox Code Playgroud)

为什么data() const需要另外满足const D是 a ranges::range?不是iterator_t<const …

c++ c++20 std-ranges

7
推荐指数
0
解决办法
87
查看次数

C++20 中的 iterator_category 和 iterator_concept 有什么区别?

C++20带来了更强大的迭代器系统,其中之一就是iterator_conceptiterator_category.

我发现C++20 中很多迭代器的iterator_conceptiterator_category是不一致的。以最著名iota_view为例

using R = decltype(views::iota(0));
static_assert(random_access_range<R>);

using I = ranges::iterator_t<R>;
static_assert(same_as<typename I::iterator_category, input_iterator_tag>);
static_assert(same_as<typename I::iterator_concept,  random_access_iterator_tag>);
Run Code Online (Sandbox Code Playgroud)

虽然是Rmodels random_access_range,但iterator_category它的迭代器的the只是一个input_iterator_tag,与iterator_concept.

为什么C++20引入iterator_concept?它的目的是什么?如果我实现我自己的迭代器,我该如何界定iterator_conceptiterator_category正确?是否iterator_category仍然在C ++ 20的意思?

c++ iterator range-v3 c++20 std-ranges

7
推荐指数
1
解决办法
201
查看次数

三元运算符应用于不同的 lambda 会产生不一致的结果

考虑以下内容,它使用三元运算符来获取两个 lambda 的公共函数指针类型

int main() {
  true ? [](auto) noexcept {} : [](int) {};
}
Run Code Online (Sandbox Code Playgroud)

GCC-trunk 仅在 C++14 中接受它,但在 C++17/20 中拒绝它(演示):

<source>:2:8: error: operands to '?:' have different types 'main()::<lambda(auto:1)>' and 'main()::<lambda(int)>'
    2 |   true ? [](auto) noexcept {} : [](int) {};
      |   ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

Clang-trunk 在所有 C++14/17/20 模式下接受它(演示)。

MSVC-trunk 仅在 C++20 中接受它,但在 C++14/17 中拒绝它(演示):

<source>(2): error C2446: ':': no conversion from 'main::<lambda_01e5bb79b5a210014fb78333f6af80f9>' to 'main::<lambda_57cf6f5767bc1bee4c1e1d9859a585d2>'
<source>(2): note: No user-defined-conversion operator available that can perform this …
Run Code Online (Sandbox Code Playgroud)

c++ lambda language-lawyer noexcept c++20

7
推荐指数
1
解决办法
267
查看次数

运行时 std::format 可能吗?

我可以使用运行时以 std::format 定义的格式字符串吗?

这似乎是在说你不能;所有格式字符串都是编译时的事情。我可以发誓我是在几个月前才这么做的,也许是在标准回归之前。

#include <iostream>
#include <string>
#include <format>

std::string centre(std::string& string, const int width, const char fillchar = ' '){
    if (width <= string.size())
        return string;
    
    string = std::format("|{0:{1}^{2}}|", string, fillchar, width); //line 25
    return string;
}

int main() {
   std::cout << centre(s, 10, '*');
}
Run Code Online (Sandbox Code Playgroud)

在构建时,我收到错误

string.cpp(25,24): 错误 C7595: 'std::_Basic_format_string<char,row::string::str &,const size_t &,const char &>::_Basic_format_string': 对立即函数的调用不是常量表达

c++ c++20 stdformat

7
推荐指数
1
解决办法
2847
查看次数

用三向运算符嵌套生成比较运算符?

考虑以下两个过载operator<=>S

#include <compare>

struct S {};

int operator<=>(S, int) { return 0;  } #1
S   operator<=>(S,   S) { return {}; } #2
Run Code Online (Sandbox Code Playgroud)

如果我比较的对象Sint,在#1将产生正确的运营商对我来说,这么喜欢表达S{} <= 00 < S{}0 <=> S{}将只是罚款

但是,如果我将一个对象S与其他对象进行比较S

S{} < S{};
Run Code Online (Sandbox Code Playgroud)

那么这将被重写为(S{} <=> S{}) < 0. 既然(S{} <=> S{})会返回 other S,我们回到原点问题:S与 a 进行比较int。目前,我们没有operator<(S, int),因此#1 …

c++ language-lawyer spaceship-operator c++20

6
推荐指数
1
解决办法
119
查看次数

在一行上获取 clang-format 格式的 require-expression

这是我的代码:

if constexpr (requires { { N::uuid() } -> std::convertible_to<score::uuid_t>; })
Run Code Online (Sandbox Code Playgroud)

clang-format (14, 15) 坚持将其格式化为 5 行:

if constexpr (requires {
                {
                  N::uuid()
                  } -> std::convertible_to<score::uuid_t>;
              })
Run Code Online (Sandbox Code Playgroud)

这太疯狂了,我怎样才能确保它保持在一行上而不必注释每一行?

c++ code-formatting clang-format c++20

6
推荐指数
1
解决办法
355
查看次数

使用 C++20 范围避免循环

我被分配了一项任务,需要在考虑到几个限制的情况下解决问题。重点是强制使用 STL 算法、迭代器和新的 c++20 功能,包括ranges. 然而,我已经阅读了几个小时的范围,但我仍然无法弄清楚如何在考虑到所有限制的情况下实现该问题。我简化了问题并删除了具体细节以使其更加通用。

问题:

编写一个函数,该函数 1) 接受自定义对象的向量2) 返回不同类型input的向量,其中包含满足某些条件的每个对象的元素。添加的值基于输入对象的属性。input

我意识到这可能听起来很晦涩,所以这里有一个简单的例子。对于形状的输入向量,其中每个形状都有一个名称和一个区域:

vector<Shapes> input{ { "Square", 10 }, { "Triangle", 30 } , { "Square", 1 }, { "Circle", 30 }, { "Triangle", 15 } };
Run Code Online (Sandbox Code Playgroud)

返回枚举向量

enum Color { RED, BLUE, GREEN };
Run Code Online (Sandbox Code Playgroud)

这样为每个 Square 或 Circle 添加一个枚举。枚举的值是根据每个 Shape 的面积确定的。因此,假设面积大于 20,则添加红色,否则添加绿色。

所以在这种情况下我们会返回{ GREEN, GREEN, RED }

这一切都很好,可以通过多种方式实施,但限制因素使其变得非常困难。

限制条件:

  • 没有循环或递归
  • std::for_each
  • 没有其他数据结构std::vector
  • 没有内存分配(除了返回向量的一次性分配)
  • 没有通过引用 lambda 捕获或可变 lambda
  • 无法修改输入向量

我的教授声称“c++20 范围使这项任务特别简单”。但即使在阅读了几个小时的范围后,我什至不知道该从哪里开始。我当前的思路是创建 a …

c++ c++20 std-ranges

6
推荐指数
1
解决办法
546
查看次数