constexpr 宣告的物件:不僅是 const,其值在編譯期可知。
constexpr 宣告的函式:若實參為編譯期常數,返回值在編譯期計算;否則退化為執行期普通函式。並不保證返回 const 或編譯期結果,這正是其威力所在——同一函式服務編譯期與執行期雙重場景。
int sz = 10; // 執行期變數
constexpr auto arraySize1 = sz; // 錯誤:sz 編譯期不可知
constexpr auto arraySize2 = 10; // 正確:10 為編譯期常數
std::array data; // 正確:arraySize2 可作模板參數
const auto arraySize3 = sz; // 正確:const 不要求編譯期初始化
std::array data2; // 錯誤:arraySize3 編譯期不可知
所有 constexpr 物件皆為 const,但非所有 const 物件皆為 constexpr。 需編譯期常數的上下文(陣列大小、模板參數、枚舉值、對齊指定等)必須使用 constexpr。
constexpr int pow(int base, int exp) noexcept {
// C++14 寫法:迴圈、區域變數、多重 return 均合法
auto result = 1;
for (int i = 0; i < exp; ++i) result *= base;
return result;
}
constexpr auto numConds = 5;
std::array results; // 編譯期計算 3^5 = 243
// 執行期調用同樣合法
auto base = readFromDB("base");
auto exp = readFromDB("exponent");
auto val = pow(base, exp); // 執行期計算
規則:實參皆為編譯期常數 → 編譯期計算;任一實參非編譯期常數 → 執行期計算。無需撰寫兩個版本。
內建型別(void 除外)皆為字面值型別。使用者定義型別若滿足:
constexprconstexpr則該型別亦為字面值型別,可用於 constexpr 語境:
class Point {
public:
constexpr Point(double x = 0, double y = 0) noexcept : x(x), y(y) {}
constexpr double xValue() const noexcept { return x; }
constexpr double yValue() const noexcept { return y; }
// C++14 允許 constexpr setter
constexpr void setX(double newX) noexcept { x = newX; }
constexpr void setY(double newY) noexcept { y = newY; }
private:
double x, y;
};
constexpr Point p1(9.4, 27.7);
constexpr Point p2(28.8, 5.3);
constexpr Point mid = (p1 + p2) / 2; // 編譯期完成建構、存取、運算、回傳
一旦宣告為 constexpr,即承諾長期維持編譯期可計算特性。後期移除 constexpr 將破壞使用者代碼(如模板參數、常數表達式上下文)。不要為了 noexcept/constexpr 扭曲實現(如吞沒異常轉錯誤碼),得不償失。
constexpr 物件為 const 且編譯期初始化。constexpr 函式接受編譯期實參時編譯期計算,否則執行期計算。constexpr 物件/函式適用語境遠廣於非 constexpr 對應物。constexpr 是介面一部分,意味著長期承諾。