记录coding or reading时遇到的一些有趣的C++ tricks.
##
在预处理过程中通知预处理器将##左边和右边的符号连接起来。
e.g.:
1
2
3
4
5
#define f(g, g2) g##g2
int main() {
int var12 = 100;
printf("%d", f(Var, 12)); // equal to printf("%d", var12);
}
attribute((flatten))
__attribute__((always_inline))存在一种缺陷,即任何调用使用该属性修饰的函数的地方都会将函数内联,而不考虑该函数本身的长度。在极端情况下,由于内联产生的函数过大编译器会将其忽略。
e.g.:
1
2
3
4
5
6
7
8
9
10
__attribute__((always_inline)) inline void do_thing(int input) {
// do something.
}
void hot_code() {
while (condition) {
...
do_thing(y);
...
}
}
此时将会产生巨大的可执行文件,较长的编译时间和更差的cache局部性。
使用__attribute__((flatten))
进行替代,编译器将会在合适的地方选择内联而在其他地方保持原样,从而尽可能避免inline的缺点。
attribute((constructor)) & attribute((destructor))
GNU C的feature,constructor用于在main函数之前调用被该标记修饰的函数,destructor用于在main函数返回或调用exit后调用被destructor修饰的函数,用于初始化程序数据。
extern “C”
实际上是一个链接规范。在使用C++编译器,需要使用C头文件时使用,编译器将其编译成C++ ABI,以供链接器链接。
decltype(auto)
Typically its use is to allow auto
declarations to use the decltype
rules on the given expression.
返回类型转发:
在non-generic代码中,可以自行选择将引用作为返回类型:
auto const& Example(int const& i) {
return i;
}
但是在generic code中,如果希望实现完美转发一个返回类型,而不需要知道这个类型是一个值还是引用,那么需要使用decltype(auto)来实现:
tempate <class Fun, class... Args>
decltype(auto) Example(Fun fun, Args&&... args) {
return fun(std::forward<Args>(args)...);
}
延迟嵌套模板中的返回类型推导
template <int i>
struct Int{};
constexpr auto iter(Int<0>) -> Int<0>;
template<int i>
constexpr auto iter(<Int<i>) -> decltype(auto)
{return iter(Int<i - 1>{})}
int main() {decltype(iter(Int<10>{}))a;}
1
2
decltype(i):返回i的类型
decltype((i)): 返回i的引用类型
decltype(auto)和auto作为返回类型的区别:
expression | auto | decltype(auto) |
---|---|---|
10 | int | int |
xx | int | int |
(x) | int | int& |
f() | int | int && |
我的一些不成熟的想法: auto类型推导似乎只能推导出来值类型,而decltype(auto)可以推导出左值引用、右值引用,因此在不想区分参数是引用类型还是值类型时,适合用decltype(auto),而在只想要值类型时,可以直接使用auto
reference:
2(c++ - What are some uses of decltype(auto)? - Stack Overflow)
unordered_map.emplace
返回一个pair,第一个元素是迭代器,第二个元素是布尔值
如果发生了插入,则布尔值为true,迭代器指向新插入的元素,如果没有发生插入,则布尔值为false,迭代器指向已经存在的元素。