当您尝试使用constexpr时,main
如下所示:
constexpr int main()
Run Code Online (Sandbox Code Playgroud)
gcc和clang抱怨:
错误:无法声明':: main'为内联
错误:'main'不允许声明为constexpr
让我们看看constexpr函数的要求是什么:
constexpr函数必须满足以下要求:
什么是LiteralType?
文字类型是以下任何一种
功能主体必须包括什么?
以下示例:
constexpr int main() { ; }
constexpr int main() { return 42; }
constexpr int main() {
// main defaults to return 0
}
Run Code Online (Sandbox Code Playgroud)
似乎符合所有这些要求.还有这个,main
是在程序开始之前运行的特殊功能.您可以从main运行constexpr函数,并且为了将constexpr标记为constexpr,它必须在constexpr上下文中运行.
那么为什么main
不允许成为constexpr?
最近在回答问题时,我意识到只要表达式被包围,逗号运算符就被允许在C++ 11中的常量表达式中()
,例如:
int a[ (1, 2) ] ;
Run Code Online (Sandbox Code Playgroud)
在C++ 11中,禁止在常量表达式中使用逗号运算符,来自草案预C++ 11标准部分5.19
常量表达式(强调我的):
[...]特别是,除了sizeof表达式,不应使用函数,类对象,指针或引用,并且不得使用赋值,递增,递减,函数调用或逗号运算符.
为什么逗号运算符不允许在C++ 11之前的常量表达式中,为什么解除了这个限制?
TL; DR
给出以下代码:
int* ptr;
*ptr = 0;
Run Code Online (Sandbox Code Playgroud)
在应用间接之前,是否*ptr
需要进行左值到右值的转换ptr
?
该标准涵盖了许多地方的左值到左值的主题,但似乎没有指定足够的信息来确定*运算符是否需要这样的转换.
细节
在左值到右值的转换是覆盖在N3485的部分4.1
左值到右值转换段落1和说(重点矿山前进):
可以将非函数非数组类型T的glvalue(3.10)转换为prvalue.53如果T是不完整类型,则需要进行此转换的程序是错误的.如果glvalue引用的对象不是T类型的对象,并且不是从T派生的类型的对象,或者如果该对象未初始化,则需要此转换的程序具有未定义的行为.[...]
那么*ptr = 0;
转换需要吗?
如果我们转到4
第1节,它说:
[...] 如果需要,标准转换序列将应用于表达式 ,以将其转换为所需的目标类型.
那么什么时候需要呢?如果我们看一下5
表达式,第9段中提到了左值到右值的转换,它说:
每当glvalue表达式作为操作符的操作数出现时,该操作符需要该操作数的prvalue,左值到右值(4.1),数组到指针(4.2)或函数到指针(4.3)标准转换是用于将表达式转换为prvalue.[...]
和第11段说:
在某些情况下,表达式仅出现其副作用.这样的表达式称为丢弃值表达式.[...]当且仅当表达式是volatile限定类型的左值并且它是以下之一时,才应用左值到右值转换(4.1). ...]
两段似乎都不适用于此代码示例和5.3.1
一元运算符第1段它说:
一元*运算符执行间接:它所应用的表达式应该是指向对象类型的指针,或指向函数类型的指针,结果是指向表达式指向的对象或函数的左值.如果表达式的类型是"指向T的指针",则结果的类型为"T".[注意:通过指向不完整类型(cv void除外)的指向的间接有效.由此获得的左值可以以有限的方式使用(例如,初始化参考); 这个左值不能转换为prvalue,见4.1. - …
我一直收到编译警告,但我不知道如何解决它:
'%d' expects argument of type 'int', but argument 2 has type 'long unsigned int' [
Run Code Online (Sandbox Code Playgroud)
程序运行正常,但我仍然收到编译警告:
/* Sizeof.c--Program to tell byte size of the C variable */
#include <stdio.h>
int main(void) {
printf("\nA Char is %d bytes", sizeof( char ));
printf("\nAn int is %d bytes", sizeof( int ));
printf("\nA short is %d bytes", sizeof( short ));
printf("\nA long is %d bytes", sizeof( long ));
printf("\nA long long is %d bytes\n", sizeof( long long ));
printf("\nAn unsigned Char is %d …
Run Code Online (Sandbox Code Playgroud) 我有以下代码:
uint16_t getLastMarker(const std::string &number);
...
const auto msgMarker = getLastMarker(msg.number) + static_cast<uint16_t>(1);
static_assert(std::is_same<decltype(msgMarker), const int>::value, "Should fail");
static_assert(std::is_same<decltype(msgMarker), const uint16_t>::value, "Should not fail");
Run Code Online (Sandbox Code Playgroud)
我希望第一个断言会失败而第二个断言不会失败.然而,gcc 4.9.2
并clang 3.6
做相反的事情.如果我在我的代码中使用uint16_t而不是auto,则正确的断言失败而另一个成功.
PS最初我只是1
代替static_cast<uint16_t>(1)
并且认为问题是由数字文字1
具有int类型但错误断言甚至在此处显式转换后失败的事实引起的.
使用Clang 3.5,3.6或3.7,带有std=c++1y
以下代码的标志不能编译:
#include <iostream>
auto foo(auto bar) { return bar; }
int main() {
std::cout << foo(5.0f) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
给出的错误是:
错误:函数原型中不允许'auto'
我使用g ++ 4.9没有错误.是否因为Clang尚未实现此功能而产生此错误,还是因为我不被允许这样做而且GCC以某种方式允许它?
我收到错误<:无法在g ++编译器上开始模板参数列表.码
template<typename T> class SomeClass;
class Class;
SomeClass<::Class>* cls;
Run Code Online (Sandbox Code Playgroud) 当我初始化下面的数组时,所有输出看起来都没问题,除了values[3]
.出于某种原因,values[3]
初始化为values[0]+values[5]
输出非常大的数字.我的猜测是,我在尝试分配values[0]+values[5]
之前将它们妥善存储在内存中,但是如果有人能够解释那将是很好的.
int main (void)
{
int values[10] = {
[0]=197,[2]=-100,[5]=350,
[3]=values[0] + values[5],
[9]= values[5]/10
};
int index;
for (index=0; index<10; index++)
printf("values[%i] = %i\n", index, values[index]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出如下:
values[0] = 197
values[1] = 0
values[2] = -100
values[3] = -1217411959
values[4] = 0
values[5] = 350
values[6] = 0
values[7] = 0
values[8] = 0
values[9] = 35
Run Code Online (Sandbox Code Playgroud) c arrays runtime-error designated-initializer unspecified-behavior
请考虑以下代码:
#include <iostream>
struct Data
{
int x, y;
};
Data fill(Data& data)
{
data.x=3;
data.y=6;
return data;
}
int main()
{
Data d=fill(d);
std::cout << "x=" << d.x << ", y=" << d.y << "\n";
}
Run Code Online (Sandbox Code Playgroud)
这d
是从返回值复制初始化的fill()
,但在返回结果之前fill()
写入d
自身.我关心的是d
在初始化之前非常简单地使用它,并且在一些(所有?)情况下使用未初始化的变量会导致不确定的行为.
那么这段代码是有效的,还是有未定义的行为?如果它有效,一旦Data
停止POD或在其他情况下,行为是否会变得不确定?
参数类型相同的静态和非静态成员函数不能重载。但是,如果成员函数是模板并且其中之一有requires
子句,那么所有编译器都允许它。但是当调用这两个成员函数时就会出现问题:
struct A {
static int f(auto) { return 1; }
int f(auto) requires true { return 2; }
};
int main() {
[[maybe_unused]] int (A::*y)(int) = &A::f; // ok everywhere (if no below line)
[[maybe_unused]] int (*x)(int) = &A::f; //ok in GCC and Clang (if no above line)
}
Run Code Online (Sandbox Code Playgroud)
如果只剩下一行(任意),main()
则 GCC 和 Clang 接受该程序。但是当两行都main()
存在时,Clang 会打印
error: definition with same mangled name '_ZN1A1fIiEEiT_' as another definition
Run Code Online (Sandbox Code Playgroud)
GCC 报告内部编译器错误。演示: https: //gcc.godbolt.org/z/4c1z7fWvx
所有编译器在接受struct …