标签: c++20

是否可以根据 C++20 中稍后的运行时决定存在不同的隐式对象?

这个问题是指在最新的C++20草案中增加了P0593

这是我的例子:

#include <cstdlib>
#include <cstdio>

void foo(void *p)
{
    if ( std::getchar() == 'i' )
    {
        *(int *)p = 2;
        std::printf("%d\n", *(int *)p);
    }
    else
    {
        *(float *)p = 2;
        std::printf("%f\n", *(float *)p);
    }
}

int main()
{
    void *a = std::malloc( sizeof(int) + sizeof(float) );
    if ( !a ) return EXIT_FAILURE;

    foo(a);
    // foo(a);    [2]
}
Run Code Online (Sandbox Code Playgroud)

此代码是否针对最新草案下的所有输入进行了明确定义?

P0593 中表达的基本原理非常清楚[2],如果两个用户输入项不同,取消注释将导致由于严格的别名违规而导致未定义的行为。隐式对象创建应该只发生一次,在malloc; 它不是由foo.

对于程序的任何实际运行,都存在一个未指定的隐式对象集的成员,可以使程序定义良好。但是我不清楚 [intro.object]/10 中提到的隐式对象创建的选择是否必须在malloc发生时进行;或者决定是否可以“时间旅行”。

对于将二进制 blob 读入缓冲区然后做出如何访问它的运行时决定(例如反序列化;并且标头告诉我们是浮点数还是整数即将出现)的程序,可能会出现同样的问题。

c++ language-lawyer c++20

11
推荐指数
1
解决办法
322
查看次数

如何使用 Godbolt(编译器资源管理器)测试 C++ 模块?

为了在 C++20 中使用自编模块提出问题或演示错误/功能,能够使用Matt Godbolt 的编译器资源管理器会很棒。

例子:

test.cpp(模块测试):

export module test;

export template<typename T>
void do_something(const T&)
{
}
Run Code Online (Sandbox Code Playgroud)

编译 clang++ -std=c++20 -stdlib=libc++ -fmodules -c -Xclang -emit-module-interface -o test.pcm test.cpp

主.cpp:

import test;

int main() {
    do_something(7);
}
Run Code Online (Sandbox Code Playgroud)

编译 clang++ -std=c++20 -stdlib=libc++ -fmodules -fimplicit-modules -fimplicit-module-maps -fprebuilt-module-path=. main.cpp

问:有没有办法用编译器资源管理器来做到这一点?

c++ c++20 c++-modules compiler-explorer

11
推荐指数
1
解决办法
1189
查看次数

为什么在 C++ 20 中从标准库容器中删除了比较运算符?

我在浏览cppreference 时看到vectorC++20 中删除了它的比较操作,并<=>引入了飞船运算符 ( )。对于许多其他标准库容器,如set和 ,可以看到同样的事情map

如何在新标准中进行比较?另外,C++20 会开始在旧代码上出错吗?

c++ spaceship-operator c++20

11
推荐指数
1
解决办法
674
查看次数

如何使用 &lt;format&gt; 标头

在一个相关的问题(“ std::string 格式,如 sprintf ”)中,我了解了这个很棒的新 C++20 标头<format>

但是,似乎没有支持 compiler。这是正确的还是有办法使用它?
我正在使用带有-std=c++2a标志的g++ 9.3,但<format>无法识别库。

#include <format> // fatal error: format: No such file or directory
#include <iostream>

int main(){
    std::cout << std::format("Hello {}!", "World");
}
Run Code Online (Sandbox Code Playgroud)

g++-9 test.cpp -o test -std=c++2a

c++ formatting g++ header-files c++20

11
推荐指数
2
解决办法
3346
查看次数

使用概念具有特定值类型的任何容器的 C++ 迭代器

我想摆脱enable_if模板中的所有邪恶s 并用 C++20 概念替换它们,但是几乎没有关于概念的任何信息,并且几乎我阅读的任何来源的语法都发生了变化。

这是一个函数,它接受任何带有MyClass值的容器的两个迭代器:

template <class IteratorType, typename = std::enable_if<std::is_same<
                                typename std::iterator_traits<IteratorType>::value_type,
                                MyClass
                            >::value, void>>
void myFunction( IteratorType begin, IteratorType end ) {}
Run Code Online (Sandbox Code Playgroud)

我知道可以使用概念转换此功能,但我找不到好的线索开始。

c++ sfinae enable-if c++-concepts c++20

11
推荐指数
3
解决办法
514
查看次数

在具有参考字段的类上放置新的

这是来自 C++20 规范 ( [basic.life]/8 )的代码示例:

struct C {
  int i;
  void f();
  const C& operator=( const C& );
};

const C& C::operator=( const C& other) {
  if ( this != &other ) {
    this->~C();              // lifetime of *this ends
    new (this) C(other);     // new object of type C created
    f();                     // well-defined
  }
  return *this;
}

int main() {    
  C c1;
  C c2;
  c1 = c2;   // well-defined
  c1.f();    // well-defined; c1 refers to a new object of type …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer c++20 stdlaunder

11
推荐指数
2
解决办法
329
查看次数

std::ranges::begin 和 std::begin 有什么区别?

std::begin和 new 和有什么不一样std::ranges::begin?(同样为endsize等等)

两者似乎工作相同:

#include <iostream>
#include <vector>
#include <array>
#include <ranges>

template<std::ranges::range R>
void printInfo(const R &range)
{
    std::cout << (std::ranges::begin(range) == std::begin(range));
}

template<class T>
struct X
{
    std::vector<T> v;

    auto begin() const { return v.begin(); }
    auto end() const { return v.end(); }
};

int main()
{
    printInfo(std::vector{1, 2, 3, 4});
    printInfo(std::array{1, 2, 3, 4});
    printInfo(X<int>{{1, 2, 3, 4}});

    int oldSchool[]{1, 2, 3, 4};
    printInfo(oldSchool);
}
Run Code Online (Sandbox Code Playgroud)

1111按预期编译和打印。

难道ranges::begin …

c++ range c++20 std-ranges

11
推荐指数
1
解决办法
610
查看次数

为什么在定义自定义点对象时需要删除函数?

从 libstdc++<concepts>头文件:

  namespace ranges
  {
    namespace __cust_swap
    {
      template<typename _Tp> void swap(_Tp&, _Tp&) = delete;
Run Code Online (Sandbox Code Playgroud)

从 MS-STL<concepts>标头:

namespace ranges {
    namespace _Swap {
        template <class _Ty>
        void swap(_Ty&, _Ty&) = delete;
Run Code Online (Sandbox Code Playgroud)

我从未遇到过= delete;要禁止调用复制/移动赋值/ctor 的上下文之外的情况。

我很好奇这是否有必要,所以我= delete;像这样注释了库中的部分:

// template<typename _Tp> void swap(_Tp&, _Tp&) = delete;
Run Code Online (Sandbox Code Playgroud)

看看下面的测试用例是否编译。

#include <concepts>
#include <iostream>

struct dummy {
    friend void swap(dummy& a, dummy& b) {
        std::cout << "ADL" << std::endl;
    }
};

int main()
{
    int a{};
    int …
Run Code Online (Sandbox Code Playgroud)

c++ stl language-lawyer c++20 customization-point

11
推荐指数
2
解决办法
305
查看次数

Why do I not get guaranteed copy elision with std::tuple?

I would expect that in C++20 the following code prints nothing between prints of A and B (since I expect guaranteed RVO to kick in). But output is:

A

Bye

B

C

Bye

Bye

So presumably one temporary is being created.

#include <iostream>
#include <tuple>
struct INeedElision{
    int i;
    ~INeedElision(){
        std::cout << "Bye\n";
    }
};

std::tuple<int, INeedElision> f(){
    int i = 47;
    return {i, {47}};
}

INeedElision g(){
    return {};
}

int main()
{   
    std::cout << "A\n"; 
    auto x = …
Run Code Online (Sandbox Code Playgroud)

c++ copy-elision rvo stdtuple c++20

11
推荐指数
1
解决办法
455
查看次数

C++20“透明可替换”关系

在 C++20 的最终工作草案(以及下面链接的最新公开可用草案)中,关于如何允许对象替换其他对象,[basic.life] 的措辞已经改变,以便指针、引用和对象的name 自动引用新对象。为此,引入了“透明可替换”的关系。但是,我不确定我是否正确理解了这一点。考虑这个例子:

struct X {int a = 3; float b;};
X x;
new(&x.a) int(5);
x.a == 5 // true without std::launder?
Run Code Online (Sandbox Code Playgroud)

在 C++17 中这当然是正确的,因为旧的 int 既不是 const 对象,也不是具有 const 非静态成员的类。

然而,现在新的透明可替换关系可能不再允许这样做了。在考虑新旧 int 对象的关系时,满足条件(8.1)到(8.4),但条件(8.5)呢?

o1 (旧的 int)和 o2 (新的 int)都是完整的对象(旧的 int 肯定是一个子对象,所以这部分是假的)或者 o1 和 o2 分别是对象 p1 和 p2 的直接子对象,而 p1可以透明地替换为 p2。

new int 是一个完整的对象,因为它是“自己”构造的(我们只放置了一个 new int 而不是一个新的 X)?

或者是否可以认为由于[intro.object]\2的措辞,新 int 是 x 的子对象,就像旧 int 一样,(我高度怀疑这是预期的解释,tbh),因此 x 满足p1 和 p2 …

c++ language-lawyer c++20

11
推荐指数
1
解决办法
179
查看次数