标签: c++03

C++ 03中的完美转发

如果你有这个功能

template<typename T> f(T&);
Run Code Online (Sandbox Code Playgroud)

然后尝试调用它,让我们说一个rvalue就好

f(1);
Run Code Online (Sandbox Code Playgroud)

为什么T不能被推导为const int,使得参数成为一个const int&因而可以绑定到一个rvalue?

c++ forwarding c++03

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

C++ 03是C++标准的新版本还是C++ 98的技术勘误(TC)?

我很确定我在一个权威来源上阅读(我相信它是在WG21页面上),C++ 03 不是 C++ 98的技术勘误,但它是C++标准的新版本.

但是,尽管如此,我只看到-std=c++98GCC和其他编译器的转换,而Alf P Steinbach发表了一些评论,暗示它可能确实是C++ 98的TC.

所以当我写"C++ 03"时,它是否足以提及C++ 98?作为一个相关问题,使用术语"C++ 03" 甚至是错误的吗?因为我认为如果它真的是C++ 98 TC1,那么在我看来它不能被称为C++ 03.正如我从未见过有人为C99TC3版本编写C07.

c++ standards iso c++03

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

为什么PRIu64不能在此代码中工作?

根据这个答案,我尝试打印一个uint64_t,但它给了我一个错误:

错误:在'PRIu64'之前预期``)'

以下是显示我想要做的最小代码:

#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <cstdio>

class X {
  X() {
    uint64_t foo = 0;
    printf("%07" PRIu64 ": ", foo);
  }
};

int main() {}
Run Code Online (Sandbox Code Playgroud)

这个最小的代码编译,但我的实际代码没有.但是,我尝试X::X()在我的实际代码中使用完全相同的2行,这不起作用.

我应该寻找什么来进一步调试?我的实际代码也是#include其他标题.这会导致问题吗?包含标题的顺序是否重要?

编辑 PRIu64在我的机器上定义如下:

# if __WORDSIZE == 64
#  define __PRI64_PREFIX    "l"
#  define __PRIPTR_PREFIX   "l"
# else
#  define __PRI64_PREFIX    "ll"
#  define __PRIPTR_PREFIX
# endif

# define PRIu64     __PRI64_PREFIX "u"
Run Code Online (Sandbox Code Playgroud)

c++ printf c++03

23
推荐指数
3
解决办法
2万
查看次数

C++ 03.在编译时测试rvalue-vs-lvalue,而不仅仅是在运行时

在C++ 03中,Boost的Foreach使用这种有趣的技术,可以在运行时检测表达式是左值还是左值.(我发现通过这个StackOverflow问题:C++ 03中的Rvalues)

这是一个在运行时工作演示

(这是一个更基本的问题,当我在思考我最近的另一个问题时出现.对此的答案可能有助于我们回答另一个问题.)

现在我已经详细说明了这个问题,在编译时在C++ 03中测试rvalue-ness,我会谈谈到目前为止我一直在尝试的事情.

我希望能够在编译时进行此检查.在C++ 11中很容易,但我对C++ 03很好奇.

我正在努力建立他们的想法,但也会对不同的方法持开放态度.他们的技术的基本思想是将此代码放入一个宏:

true ? rvalue_probe() : EXPRESSION;
Run Code Online (Sandbox Code Playgroud)

它的左侧是'true' ?,因此我们可以确定永远不会评估EXPRESSION.但有趣的是,?:运算符的行为会有所不同,具体取决于它的参数是左值还是右值(单击上面的链接获取详细信息).特别是,它将rvalue_probe以两种方式之一转换我们的对象,具体取决于EXPRESSION是否为左值:

struct rvalue_probe
{
    template< class R > operator       R () { throw "rvalue"; }
    template< class L > operator       L & () const { throw "lvalue"; }
    template< class L > operator const L & () const { throw "const lvalue"; }
};
Run Code Online (Sandbox Code Playgroud)

这在运行时有效,因为可以捕获抛出的文本并用于分析EXPRESSION是左值还是右值.但我希望在编译时能够识别正在使用的转换. …

c++ rvalue language-lawyer c++03

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

在NULL指针上调用delete - C++ 03 vs C++ 11

在C++ 03标准中,我看到:

5.3.5删除

2如果操作数具有类类型,则通过调用上述转换函数将操作数转换为指针类型,并使用转换后的操作数代替本节其余部分的原始操作数.在任一替代方案中,如果操作数的值delete是空指针,则操作无效.在第一个备选(删除对象)中,操作数的值delete应该是指向非数组对象的指针或指向表示此类对象的基类的子对象(1.8)的指针(第10节).如果不是,则行为未定义.在第二种方法(删除数组)中,操作数的delete值必须是由前一个数组new-expression产生的指针值.72)如果不是,则行为是未定义的.

在C++ 11 Draft Standard(N3337)中,我看到:

5.3.5删除

2如果操作数具有类类型,则通过调用上述转换函数将操作数转换为指针类型,并使用转换后的操作数代替本节其余部分的原始操作数.在第一个替代(删除对象)中,操作数的值delete可以是空指针值,指向由前一个新表达式创建的非数组对象的指针,或指向表示基础的子对象(1.8)的指针这类对象的类别(第10条).如果不是,则行为未定义.在第二个备选(删除数组)中,delete的操作数的值可以是空指针值或由先前数组new-expression产生的指针值.如果不是,则行为未定义.

我已经强调了两个标准中规范之间的差异.我觉得奇怪的是,2003标准更加强调必须如何处理NULL指针,而2011标准没有说明实现必须做什么.

  1. C++ 11标准的措辞是否在草案标准和实际标准之间发生了变化?如果是这样,怎么样?

  2. 如果标准草案的措辞在实际标准中保持不变,那么在2003年和2011年之间将强有力的陈述改为几乎没有任何理由的理由是什么?

c++ language-lawyer delete-operator c++11 c++03

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

*&++我在C++ 03中导致未定义的行为吗?

另一个答案有人指出,之前C++ 11,其中i是一个int,则使用表达式:

*&++i
Run Code Online (Sandbox Code Playgroud)

导致未定义的行为.这是真的?

另一个答案是在评论中进行了一些讨论,但似乎并不令人信服.

c++ undefined-behavior sequence-points language-lawyer c++03

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

最令人烦恼的解析与阵列访问

在查看一些C++ 03代码时,我发现了一个让我感到困惑的最令人烦恼的解析实例:

#include <sstream>
#include <string>

int main(int, char** argv)
{
    std::stringstream ss(std::string(argv[0]));
}
Run Code Online (Sandbox Code Playgroud)

wandbox上的实例

在上面的代码片段中,ss是一个函数的声明,它接受std::string*并返回std::stringstream.

怎么std::string(argv[0])解析为std::string*

直觉上,我认为这argv[0]是明确无误的访问argv.

c++ most-vexing-parse c++03

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

更好的方式来说x == Foo :: A || x == Foo :: B || x == Foo :: C || ...?

假设我有一堆众所周知的值,就像这样(但const char *只是一个例子,它可能会更复杂):

const char *A = "A", *B = "B", *C = "C", *D = "D", *E = "E", *F = "F", *G = "G";
Run Code Online (Sandbox Code Playgroud)

现在让我们说如果某个表达式的结果位于其中的一个子集中,我希望以特定方式运行:

if (some_complicated_expression_with_ugly_return_type == A ||
    some_complicated_expression_with_ugly_return_type == C ||
    some_complicated_expression_with_ugly_return_type == E ||
    some_complicated_expression_with_ugly_return_type == G)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

我发现自己经常输入这种东西,我想要一个简写.

如果语言是Python,我可以很容易地说:

if some_complicated_expression_with_ugly_return_type in [A, C, E, G]:
    ...
Run Code Online (Sandbox Code Playgroud)

有一种众所周知的,可移植的方式让我在C++ 03中表达同样的东西吗?

请注意,返回类型本身很难看(几乎和lambda表达式的返回类型一样难看),所以我当然不希望将它存储在局部变量中.

但返回类型并没有必须匹配的常量的-例如,如果返回类型是std::string,这将不会是隐式转换为const char *,但operator ==将是比较完美的罚款.

到目前为止,我所拥有的最佳解决方案是:

const char …
Run Code Online (Sandbox Code Playgroud)

c++ c++03

20
推荐指数
4
解决办法
1242
查看次数

为什么在C++ 11中删除了对逗号运算符的限制在常量表达式中删除了?

最近在回答问题时,我意识到只要表达式被包围,逗号运算符就被允许在C++ 11中的常量表达式中(),例如:

int a[ (1, 2) ] ;
Run Code Online (Sandbox Code Playgroud)

在C++ 11中,禁止在常量表达式中使用逗号运算符,来自草案预C++ 11标准部分5.19 常量表达式(强调我的):

[...]特别是,除了sizeof表达式,不应使用函数,类对象,指针或引用,并且不得使用赋值,递增,递减,函数调用或逗号运算符.

为什么逗号运算符不允许在C++ 11之前的常量表达式中,为什么解除了这个限制?

c++ language-lawyer constant-expression c++11 c++03

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

引用声明是否为引用引用了新名称?

这个问题中,我们已经知道RVO不能应用于像这样的表达式p.first.

在评论中,还建议RVO通常不适用于像r声明之类的表达式auto& r = p.first.标准是否要求这种行为尚不清楚.

在具有类返回类型的函数的return语句中,当表达式是非易失性自动对象名称时(除了函数参数或由处理程序的异常声明引入的变量([except.handle]) ))具有与函数返回类型相同的类型(忽略cv-qualification),通过将自动对象直接构造到函数的返回值中,可以省略复制/移动操作

在下面的代码中,对象r名称是否也称为o,当RVO在return语句中形成表达式时允许使用RVO ?

int o = 42;
int& r = o;
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer c++11 c++03 c++14

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