Home C++ tricks
Post
Cancel

C++ tricks

记录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作为返回类型的区别:

expressionautodecltype(auto)
10intint
xxintint
(x)intint&
f()intint &&

我的一些不成熟的想法: auto类型推导似乎只能推导出来值类型,而decltype(auto)可以推导出左值引用、右值引用,因此在不想区分参数是引用类型还是值类型时,适合用decltype(auto),而在只想要值类型时,可以直接使用auto

reference:

[1]c++ - What is the difference between auto and decltype(auto) when returning from a function? - Stack Overflow

2(c++ - What are some uses of decltype(auto)? - Stack Overflow)

unordered_map.emplace

返回一个pair,第一个元素是迭代器,第二个元素是布尔值

如果发生了插入,则布尔值为true,迭代器指向新插入的元素,如果没有发生插入,则布尔值为false,迭代器指向已经存在的元素。

This post is licensed under CC BY 4.0 by the author.