编译是预处理之后的阶段,它的输入是(经过预处理的)C++ 源码,输出是二进制可执行文件(也可能是汇编文件、动态库或者静态库)。这个处理动作就是由编译器来执行的。

编译阶段的特殊性在于,它看到的都是 C++ 语法实体,比如 typedef、using、template、struct/class 这些关键字定义的类型,而不是运行阶段的变量。

下面举例说明

template<int N>
struct fib                   // 递归计算斐波那契数列
{
	static const int value = fib<N - 1>::value + fib<N - 2>::value;
};

template<>
struct fib<0>                // 模板特化计算fib<0>
{
	static const int value = 1;
};

template<>
struct fib<1>               // 模板特化计算fib<1>
{
	static const int value = 1;
};

// 调用后输出2,3,5,8
cout << fib<2>::value << endl;
cout << fib<3>::value << endl;
cout << fib<4>::value << endl;
cout << fib<5>::value << endl;

属性

可以把它理解为给变量、函数、类等“贴”上一个编译阶段的“标签”,方便编译器识别处理。C++11 之后有标准支持。

[[noreturn]]  // 属性标签
int func(bool falg) {  // 函数绝不会返回任何值
	throw std::runtime_error("xxx");
}

不过,在 C++11 里只定义了两个属性:“noreturn”和“carries_dependency”,它们基本上没什么大用处。

C++14 的情况略微好了点,增加了一个比较实用的属性“deprecated”,用来标记不推荐使用的变量、函数或者类,也就是被“废弃”。

[[deprecated("deadline:2020-12-31")]]      // C++14 or later
int old_func();

GCC 还额外扩展了一些属性,如下