小编gez*_*eza的帖子

在转换运算符不明确时选择它们

我有两种类型:

struct A { };
struct B { };
Run Code Online (Sandbox Code Playgroud)

我有功能AB:

void fnA(A); // there are a lot of these functions
void fnB(B);
Run Code Online (Sandbox Code Playgroud)

我有一个类型,可转换为AB:

struct Foo {
    operator A();
    operator B();
};
Run Code Online (Sandbox Code Playgroud)

所以,我可以打电话fnAfnB:

fnA(Foo()); // fine
fnB(Foo());
Run Code Online (Sandbox Code Playgroud)

现在,我有重载功能:

void fn(A);
void fn(B);
Run Code Online (Sandbox Code Playgroud)

我不能打电话给他们Foo,因为它含糊不清:

fn(Foo()); // ambiguous, which fn is called
Run Code Online (Sandbox Code Playgroud)

我希望fn(A)在这种情况下被召唤.

我可以添加第三个fn重载:

inline void fn(Foo foo) {
    fn(A(foo));
}
Run Code Online (Sandbox Code Playgroud)

但我不喜欢这种方式,因为我有很多fn功能,而且我不想大大增加功能的数量(我有fn …

c++

3
推荐指数
1
解决办法
77
查看次数

Function interleaving in pre C++17

Look at this simple function call:

f(a(), b());
Run Code Online (Sandbox Code Playgroud)

According to the standard, call order of a() and b() is unspecified. C++17 has the additional rule which doesn't allow a() and b() to be interleaved. Before C++17, there was no such rule, as far as I know.

Now, look at this simple code:

int v = 0;

int fn() {
    int t = v+1;
    v = t;
    return 0;
}

void foo(int, int) { }

int main() {
    foo(fn(), fn());
} …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer c++11 c++14 c++17

3
推荐指数
1
解决办法
187
查看次数

严格混叠规则对“包括上述类型之一的聚合或联合类型”的严格别名规则有什么影响?

以前,在basic.lval中有以下要点:

集合或联合类型,在其元素或非静态数据成员(递归包括子集合或包含的联合的元素或非静态数据成员)中包括上述类型之一,

在当前草案中,它已消失。

WG21的网站上有一些背景信息:http : //www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1359r0.html#2051

7.2.1 [basic.lval]第10段的别名规则是从C改编而成,并增加了C ++。但是,许多要点要么不适用,要么被其他要点包含。例如,在C中需要为集合和联合类型提供结构分配,这在C ++中是通过C ++中的构造函数和赋值运算符完成的,而不是通过访问完整对象来完成的。

谁能告诉我,这是什么意思?这个严格的别名规则与C中的结构分配有什么关系?

cppreference对此规则说:

这些项目符号描述了C ++中不会出现的情况

我不明白,为什么这是真的。例如,

struct Foo {
    float x;
};

float y;
float z = reinterpret_cast<Foo*>(&y)->x;
Run Code Online (Sandbox Code Playgroud)

最后一行似乎完成了项目要点描述的内容。它通过包含(成员)的集合访问y(a )。floatfloatx

谁能对此有所启发?

c++ struct strict-aliasing language-lawyer

3
推荐指数
1
解决办法
109
查看次数

C++20中隐式创建对象,理解提案的类型双关例子

我试图完全理解 C++20 的一个新特性,即对象的隐式创建。

提案中的“3.3 类型双关语”部分中有此示例:

我们不希望以下示例有效:

float do_bad_things(int n) {
    alignof(int) alignof(float) char buffer[max(sizeof(int), sizeof(float))];
    *(int*)buffer = n;                      // #1
    new (buffer) std::byte[sizeof(buffer)]; // #X
    return (*float*)buffer;                 // #2
}
Run Code Online (Sandbox Code Playgroud)

提议的规则将允许 int 对象出现以使第 1 行有效(在每种情况下),并允许浮动对象同样出现以使第 2 行有效。

为什么标有#X(由我)的行是必要的?这有什么不同吗?如果没有这条线,这个例子会不会完全一样?

我的推理是:buffer是一个字符数组,所以它隐式地创建了对象。因此,在第 1 行,int隐式创建了an 。同样,在第 2 行float,即使没有行 #X(因为buffer已经具有隐式创建对象属性),也会隐式创建a 。所以看起来#X 行没有添加任何内容。我错了吗?

c++ c++20

3
推荐指数
1
解决办法
116
查看次数

是否将指针移动到结构成员 UB?并访问它?

看看这个片段:

struct S {
    float x, y, z;
};

void fn() {
    S s = { 0, 0, 0 };
    float *p = &s.x;
    p += 2;           // 1.
    if constexpr(sizeof(S)==sizeof(float)*3) { // if S has no padding
        float t = *p; // 2.
        s.z = 1;
        float z = *p; // 3.
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  1. p += 2;UB吗?(即,从 fromp移动了两个元素s.x,所以它指向了&s.x+1
  2. 在这里,我们知道S没有填充,是float t = *p;UB?或者它是否定义明确,t应该包含的值 …

c++ language-lawyer

2
推荐指数
1
解决办法
128
查看次数

具有空初始化的对象的生命周期

目前的标准草案在[basic.life/1]中说(以前的标准有相似的措辞):

对象或引用的生命周期是对象或引用的运行时属性.如果一个对象属于类或聚合类型,并且它或其子对象之一由除了普通默认构造函数之外的构造函数初始化,则称该对象具有非空的初始化.[注意:通过简单的复制/移动构造函数进行初始化是非空的初始化. - 结束注释]类型T对象的生命周期从以下开始:

(1.1)获得具有适当对齐和T型尺寸的存储,并且

(1.2)如果对象具有非空的初始化,则其初始化完成,

看到这段代码:

alignas(int) char obj[sizeof(int)];
Run Code Online (Sandbox Code Playgroud)

basic.life/1是否意味着这里int(和其他几种类型,具有相同或更小的对齐/尺寸要求int)已经开始了它的生命周期?

这甚至意味着什么?如果一个对象已经开始它的生命周期,它是否被创建?[intro.object/1]说:

[...]通过定义([basic.def]),通过new-expression,隐式更改union的活动成员([class.union])或创建临时对象时创建对象([conv.rval],[class.temporary])[...]

因此,根据这一点,我obj(作为int)不是创建的.但它作为一个int(以及其他可能是无限类型的空间可初始化对象)的生命已经开始.

我很困惑,你能澄清一下吗?

c++ object-lifetime language-lawyer c++17

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

复制/分配基本类型

标准对基本类型的复制/分配有什么看法?

对于类类型,我们有复制构造函数,赋值运算符,它将右侧作为引用(它必须是引用,否则我们有无限递归):

struct Foo {
    Foo(const Foo &);
};
Run Code Online (Sandbox Code Playgroud)

这是如何为基本类型定义的?

看看这个例子:

const Foo foo;
Foo f = foo;

const int a = 2;
int b = a;
Run Code Online (Sandbox Code Playgroud)

在这里,f = foo;odr-uses foo,作为拷贝构造函数需要参考,对吗?如果基本类型的副本有参考参数,那么b = a也会使用odr a.是这样的吗?如果没有,它是如何处理的?

c++ language-lawyer c++17

2
推荐指数
1
解决办法
110
查看次数

在特殊情况下是否可以忽略[[nodiscard]]?

C++ 17有一个新属性[[nodiscard]].

假设我有一个Result结构,它具有以下属性:

struct [[nodiscard]] Result {
};
Run Code Online (Sandbox Code Playgroud)

现在,如果我调用一个返回的函数,Result如果我不检查返回的,我会收到警告Result:

Result someFunction();

int main() {
    someFunction(); // warning here, as I don't check someFunction's return value
}
Run Code Online (Sandbox Code Playgroud)

该程序生成:

警告:忽略使用'nodiscard'属性声明的函数的返回值[-Wunused-result]

到现在为止还挺好.现在假设,我有一个特殊的功能,我仍然想要返回Result,但如果省略检查,我不希望生成此警告:

Result someNonCriticalFunction();

int main() {
    someNonCriticalFunction(); // I don't want to generate a warning here
}
Run Code Online (Sandbox Code Playgroud)

这是因为,someNonCriticalFunction()做了一些不重要的事情(例如,类似的事情printf- 我敢打赌,没有人会一直检查其printf返回值); 大多数情况下,我不在乎它是否失败.但我还是希望它能够回归Result,就像在极少数情况下,我确实需要它Result.

有可能以某种方式这样做吗?


我不喜欢可能的解决方案:

  • 我不想把它称为(void)someNonCriticalFunction(),因为这个函数被调用了很多次,它很尴尬
  • 创建一个包装器someNonCriticalFunction(),它调用(void)someNonCriticalFunction():我不想因为这个而拥有一个不同的命名函数
  • [[nodiscard]]从Result中删除,并将其添加到每个返回的函数中 …

c++ c++17

1
推荐指数
3
解决办法
504
查看次数

“ void()”如何有用?

您不能声明void变量:

void fn() {
    void a; // ill-formed
}
Run Code Online (Sandbox Code Playgroud)

但这编译为:

void fn() {
    void(); // a void object?
}
Run Code Online (Sandbox Code Playgroud)

什么void()意思 有什么用?为什么void a;格式不正确,但void()可以?

void fn() {
    void a = void(); // ill-formed
}
Run Code Online (Sandbox Code Playgroud)

c++ void variable-declaration

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

如何避免对同一变量重复 std::forward

假设我有这个模板函数:

template <typename T>
void foo(T &&t) {
    std::forward<T>(t).foo();
    std::forward<T>(t).bar();
    std::forward<T>(t).baz();

}
Run Code Online (Sandbox Code Playgroud)

请注意,我必须std::forward对同一个变量重复多次(以确保 if Thas ref-qualified foo()// ,将调用正确的变量)bar()baz()

有没有办法避免重复std::forward?它不仅是多余的,而且还容易出错,因为我可能会忘记std::forward在某个地方添加。

c++

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

是否有可能创建更好的`std :: min`和`std :: max`版本?

随着C++ 17的新特性,是有可能创造一个更好的std::minstd::max

我的意思更好:

  • std::min/max悬挂引用的问题.
  • std::min/max不适用于不同类型(即min(short, int)需要明确指定类型min<int>(...))

我希望有一个更好的实现,其中:

  • 避免悬空引用问题(例如,min(a, 4); 正常工作)
  • 适用于不同类型(例如,min((short)4, (int)8);编译)
  • 避免不必要的对象副本(例如,如果我有一个代表一个大整数的类,它只在不可避免时复制它)

是否可以这样做,或者是std::min/max目前最好的解决方案?

c++ c++17

0
推荐指数
1
解决办法
186
查看次数

静态或动态类型用于"sizeof expr"?

是静态还是动态类型的expr使用sizeof expr

请引用C++ 17标准.

c++ static-typing sizeof language-lawyer c++17

0
推荐指数
2
解决办法
165
查看次数