我正在尝试在编译时计算字符串文字的长度.为此,我使用以下代码:
#include <cstdio>
int constexpr length(const char* str)
{
return *str ? 1 + length(str + 1) : 0;
}
int main()
{
printf("%d %d", length("abcd"), length("abcdefgh"));
}
Run Code Online (Sandbox Code Playgroud)
一切都按预期工作,程序打印4和8.由clang生成的汇编代码显示结果在编译时计算:
0x100000f5e: leaq 0x35(%rip), %rdi ; "%d %d"
0x100000f65: movl $0x4, %esi
0x100000f6a: movl $0x8, %edx
0x100000f6f: xorl %eax, %eax
0x100000f71: callq 0x100000f7a ; symbol stub for: printf
Run Code Online (Sandbox Code Playgroud)
我的问题:标准是否保证length函数将在编译时进行评估?
如果这是真的,编译时字符串文字计算的大门刚刚为我打开...例如,我可以在编译时计算哈希值等等......
鉴于c ++许多程序员提供的新工具集,旨在实现代码简化,表达性,效率,浏览旧代码并进行调整(有些无意义,有些成功)以实现他们的目标.尽管不要在这些工作上浪费太多时间,只是做出非侵入性和自包含的变化,但最佳做法是什么?
让我勾勒出明显的:
使用auto运行基于迭代器的循环:
for (std::vector<foo>::const_iterator it(lala.begin()), ite(lala.end()); it != ite;
++it);
// becomes
for (auto it(lala.cbegin()), ite(lala.cend()); it != ite; ++it);
Run Code Online (Sandbox Code Playgroud)使用tie来进行多个赋值,这些赋值只产生C风格的代码行(如何一次将多个值分配到结构中?)
a = 1;
b = 2;
c = 3;
d = 4;
e = 5;
// becomes
std::tie(a, b, c, d, e) = std::make_tuple(1, 2, 3, 4, 5);
Run Code Online (Sandbox Code Playgroud)要使类不可继承,只需将其声明为"final"并删除实现此类行为的代码http://www.parashift.com/c++-faq/final-classes.html
使用delete关键字显式隐藏构造函数/析构函数,而不是将它们声明为私有(例如,用于创建基于堆的对象的代码,不可复制的对象等)
创建简单的仿函数只是为了将单个STL算法的执行变为lambda函数(除了减少代码混乱,你还能保证内联调用)
仅使用智能指针简化对象的RAII包装
摆脱bind1st,bind2nd只需使用bind
用<type_traits>提供的标准代码替换类型特征的手写代码(Is_ptr_but_dont_call_for_const_ptrs <>等:))
停止包含现在在STL中实现的函数的boost标头(BOOST_STATIC_ASSERT vs static_assert)
为类提供移动语义(虽然这不符合脏/快/易更改的条件)
在可能的情况下使用nullptr而不是NULL宏,并删除填充指针的容器的代码,其中0已转换为对象类型
std::vector<foo*> …Run Code Online (Sandbox Code Playgroud)我正在研究核心常量表达式*中允许的内容,这在C++标准草案的5.19 常量表达式第2段中有所描述:
条件表达式是核心常量表达式,除非它涉及以下之一作为潜在评估的子表达式(3.2),但是未评估的逻辑AND(5.14),逻辑OR(5.15)和条件(5.16)操作的子表达式不考虑[注意:重载的运算符调用函数.-end note]:
并列出随后的子弹中的排除项并包括(强调我的):
- 具有未定义行为的操作 [注意:包括,例如,有符号整数溢出(第5条),某些指针算术(5.7),除零(5.6)或某些移位操作(5.8) - 结束注释];
嗯?为什么常量表达式需要此子句来涵盖未定义的行为?常量表达式是否有一些特殊的东西需要未定义的行为才能在排除中进行特殊划分?
拥有这个条款是否给了我们没有它的任何优势或工具?
作为参考,这看起来像广义常量表达式提案的最新修订版.