小编Col*_*mbo的帖子

int a [] = {1,2,}; 奇怪的逗号允许.任何特殊原因?

也许我不是来自这个星球,但在我看来,以下应该是语法错误:

int a[] = {1,2,}; //extra comma in the end
Run Code Online (Sandbox Code Playgroud)

但事实并非如此.我很惊讶,当编译这段代码在Visual Studio中,但我已经学会了不至于C++规则而言信任MSVC的编译器,所以我检查的标准,它标准允许为好.如果你不相信我,你可以看到8.5.1的语法规则.

在此输入图像描述

为什么允许这样做?这可能是一个愚蠢无用的问题,但我希望你理解我为什么这么问.如果它是一般语法规则的子案例,我会理解 - 他们决定不再使一般语法更难以在初始化列表的末尾禁止冗余逗号.但不,明确允许附加逗号.例如,在函数调用参数列表的末尾(当函数采用时...)不允许使用冗余逗号,这是正常的.

那么,是否有任何特殊原因明确允许这个冗余逗号?

c++ syntax grammar language-lawyer

325
推荐指数
15
解决办法
3万
查看次数

可以在头文件中使用lambda违反ODR吗?

可以在头文件中写入以下内容:

inline void f () { std::function<void ()> func = [] {}; }
Run Code Online (Sandbox Code Playgroud)

要么

class C { std::function<void ()> func = [] {}; C () {} };
Run Code Online (Sandbox Code Playgroud)

我想在每个源文件中,lambda的类型可能不同,因此包含的类型std::function(target_type的结果会有所不同).

这是一个ODR(一个定义规则)违规,尽管看起来像一个共同的模式和合理的事情?第二个示例是每次都违反ODR还是仅在头文件中至少有一个构造函数?

c++ lambda one-definition-rule language-lawyer c++11

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

为什么对于非TriviallyCopyable的对象,未定义std :: memcpy的行为?

来自http://en.cppreference.com/w/cpp/string/byte/memcpy:

如果对象不是TriviallyCopyable(例如标量,数组,C兼容结构),则行为未定义.

在我的工作中,我们使用std::memcpy了很长时间来按比例交换不是TriviallyCopyable的对象:

void swapMemory(Entity* ePtr1, Entity* ePtr2)
{
   static const int size = sizeof(Entity); 
   char swapBuffer[size];

   memcpy(swapBuffer, ePtr1, size);
   memcpy(ePtr1, ePtr2, size);
   memcpy(ePtr2, swapBuffer, size);
}
Run Code Online (Sandbox Code Playgroud)

从来没有任何问题.

我理解滥用std::memcpy非TriviallyCopyable对象并导致下游的未定义行为是微不足道的.但是,我的问题是:

std::memcpy当与非TriviallyCopyable对象一起使用时,为什么它本身的行为是未定义的?为什么标准认为有必要指定?

UPDATE

http://en.cppreference.com/w/cpp/string/byte/memcpy的内容已经过修改,以回应这篇文章和帖子的答案.目前的描述说:

如果对象不是TriviallyCopyable(例如标量,数组,C兼容结构),则行为是未定义的,除非程序不依赖于目标对象(不运行memcpy)的析构函数的效果和生命周期目标对象(已结束,但未开始memcpy)由其他一些方法启动,例如placement-new.

PS

@Cubbi的评论:

@RSahu如果有东西保证UB下游,它会使整个程序不确定.但我同意在这种情况下似乎可以绕过UB并相应​​地修改cppreference.

c++ memcpy object-lifetime language-lawyer c++11

67
推荐指数
5
解决办法
5355
查看次数

在修改后的异常上使用`throw;`

我有一个foo可以抛出bar异常的函数.

在我调用的另一个函数中,foo但是bar如果抛出,我可以向异常添加更多细节.(foo由于该函数的通用特性,我宁愿不将这些信息作为参数传递给它,因为它并不真正属于那里.)

所以我在调用者中这样做:

try {
    foo();
} catch (bar& ex){
    ex.addSomeMoreInformation(...);
    throw;
}
Run Code Online (Sandbox Code Playgroud)

throw重新抛出修改过的异常还是我需要使用throw ex;?后者可能会采用有价值的副本,所以我宁愿不这样做.还会throw带一个价值副本吗?我怀疑它不会.

(我知道我可以验证,但我担心绊倒一个未指定或未定义的构造,所以想知道肯定).

c++ exception-handling exception throw language-lawyer

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

是否定义了std :: is_unsigned <bool> :: value?

我想知道是否

std::is_unsigned<bool>::value
Run Code Online (Sandbox Code Playgroud)

根据标准是否明确定义?

我问这个问题因为typename std::make_unsigned<bool>::type没有明确定义.

c++ unsigned boolean language-lawyer c++14

56
推荐指数
4
解决办法
2716
查看次数

"懒惰的人的enable_if"是合法的C++吗?

我经常使用一种技术,我称之为"懒人enable_if",我使用它decltype和逗号运算符来启用基于某些模板输入的函数.这是一个小例子:

template <typename F>
auto foo(F&& f) -> decltype(f(0), void())
{
    std::cout << "1" << std::endl;
}

template <typename F>
auto foo(F&& f) -> decltype(f(0, 1), void())
{
    std::cout << "2" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

随着--std=c++11,g ++ 4.7+和Clang 3.5+愉快地编译那段代码(并且它按照我的预期工作).但是,当使用MSVC 14 CTP5时,我得到这个错误抱怨foo已经定义:

错误错误C2995:'unknown-type foo(F &&)':函数模板已经定义了c ++ - scratch main.cpp 15

所以我的问题是:"懒人enable_if"是合法的C++还是这是一个MSVC错误?

c++ sfinae visual-c++ language-lawyer c++11

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

最终是否意味着覆盖?

据我所知,override关键字声明给定的声明实现了一个基本virtual方法,如果找不到匹配的基本方法,编译应该失败.

我对该final关键字的理解是它告诉编译器没有类会覆盖这个virtual函数.

那是override final多余的吗?好像编译好了.哪些信息override final传达的final不是?这种组合的用例是什么?

c++ overriding virtual-functions final

49
推荐指数
4
解决办法
1万
查看次数

用户定义的文字中是否允许使用C++ 14位分隔符?

当clang编译以下行时,g ++ 6.1会抱怨数字分隔符(请参阅Coliru上的实例):

auto time = 01'23s;
Run Code Online (Sandbox Code Playgroud)

根据C++ 14标准(N3796),哪个编译器(如果有)是正确的?

否则,允许数字分隔符(§2.14.2)只是<chrono>库的用户定义文字(§2.14.8)中的实现细节(§20.12.5.8)?恕我直言,它应该不是,因为这些文字是在unsigned long long参数上定义的.

我记得Howard Hinnant10'000s在他的CppCon 2016演讲"A <chrono>tutorial"(在他的演讲中大约42分钟)中作为一个例子.


(请注意,我不打算编码"1分23秒",这只是偶然的,因为八进制文字0123是64 + 16 + 3 == 83.为此我应该写

auto time = 1min + 23s;
Run Code Online (Sandbox Code Playgroud)

但是这种可能误导性的解释不是问题的一部分.)

c++ language-lawyer user-defined-literals c++14 digit-separator

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

GCC接受`constexpr struct {} s;`但Clang拒绝它.谁是对的?

以下代码与GCC编译良好:

constexpr struct {} s;
Run Code Online (Sandbox Code Playgroud)

但Clang拒绝了它,出现以下错误:

错误:没有用户提供的默认构造函数,默认初始化const类型'const struct(anonymous struct at ...)'的对象

我已经测试了我能够在https://gcc.godbolt.org/找到的所有GCC和Clang版本.每个版本的GCC都接受代码,而Clang的每个版本都拒绝它.

我想知道在这种情况下哪个编译器是正确的?
标准对此有何看法?

c++ gcc clang language-lawyer constexpr

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

这真的打破了严格别名规则吗?

当我使用g ++编译这个示例代码时,我收到此警告:

警告:解除引用类型惩罚指针将破坏严格别名规则 [-Wstrict-aliasing]

代码:

#include <iostream>

int main() 
{
   alignas(int) char data[sizeof(int)];
   int *myInt = new (data) int;
   *myInt = 34;

   std::cout << *reinterpret_cast<int*>(data);
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,不是data别名int,因此将其强制转换为int不会违反严格的别名规则?或者我在这里遗漏了什么?

编辑:奇怪,当我这样定义时data:

alignas(int) char* data = new char[sizeof(int)];
Run Code Online (Sandbox Code Playgroud)

编译器警告消失了.堆栈分配是否与严格别名产生差异?事实上它是一个char[]而不是一个char*意味着它实际上不能为任何类型别名吗?

c++ strict-aliasing language-lawyer

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