คำอธิบาย
คอมไพเลอร์บางตัว (โดยเฉพาะ GCC) ใช้ความแม่นยำสูงกว่าเมื่อประเมินนิพจน์ในเวลาคอมไพล์ หากนิพจน์ขึ้นอยู่กับอินพุตและตัวอักษรคงที่เท่านั้นอาจมีการประเมินในเวลาคอมไพล์แม้ว่านิพจน์จะไม่ได้กำหนดให้กับตัวแปร constexpr สิ่งนี้จะเกิดขึ้นหรือไม่ขึ้นอยู่กับ:
- ความซับซ้อนของนิพจน์
- ขีด จำกัด ที่คอมไพลเลอร์ใช้เป็นจุดตัดเมื่อพยายามดำเนินการประเมินเวลาคอมไพล์
- ฮิวริสติกอื่น ๆ ที่ใช้ในกรณีพิเศษ (เช่นเมื่อเสียงดังขึ้นลูป)
หากนิพจน์ถูกจัดเตรียมไว้อย่างชัดเจนเช่นเดียวกับในกรณีแรกจะมีความซับซ้อนต่ำกว่าและคอมไพเลอร์มีแนวโน้มที่จะประเมินในเวลาคอมไพล์
ในทำนองเดียวกันถ้าฟังก์ชันถูกทำเครื่องหมายแบบอินไลน์คอมไพลเลอร์มีแนวโน้มที่จะประเมินค่าในเวลาคอมไพล์เนื่องจากฟังก์ชันแบบอินไลน์จะเพิ่มขีด จำกัด ที่สามารถเกิดการประเมินได้
ระดับการเพิ่มประสิทธิภาพที่สูงขึ้นยังเพิ่มเกณฑ์นี้เช่นเดียวกับในตัวอย่าง -Ofast โดยที่นิพจน์ทั้งหมดประเมินเป็นจริงบน gcc เนื่องจากการประเมินเวลาคอมไพล์ที่มีความแม่นยำสูงขึ้น
เราสามารถสังเกตพฤติกรรมนี้ได้ที่นี่ใน compiler explorer เมื่อคอมไพล์ด้วย -O1 เฉพาะฟังก์ชันที่มีเครื่องหมายอินไลน์เท่านั้นที่จะได้รับการประเมินในเวลาคอมไพล์ แต่ที่ -O3 ทั้งสองฟังก์ชันจะได้รับการประเมินตามเวลาคอมไพล์
หมายเหตุ: ในตัวอย่าง compiler-explorer ฉันใช้printfiostream แทนเพราะลดความซับซ้อนของฟังก์ชันหลักทำให้มองเห็นเอฟเฟกต์ได้ชัดเจนขึ้น
แสดงให้เห็นว่าinlineไม่มีผลกับการประเมินรันไทม์
เราสามารถมั่นใจได้ว่าจะไม่มีการประเมินนิพจน์ใด ๆ ในเวลาคอมไพล์โดยรับค่าจากอินพุตมาตรฐานและเมื่อเราทำเช่นนี้นิพจน์ทั้ง 3 จะแสดงผลเท็จตามที่แสดงไว้ที่นี่: https://ideone.com/QZbv6X
#include <cmath>
#include <iostream>
bool is_cube(double r)
{
return floor(cbrt(r)) == cbrt(r);
}
bool inline is_cube_inline(double r)
{
return floor(cbrt(r)) == cbrt(r);
}
int main()
{
double value;
std::cin >> value;
std::cout << (floor(cbrt(value)) == cbrt(value)) << std::endl;
std::cout << (is_cube(value)) << std::endl;
std::cout << (is_cube_inline(value)) << std::endl;
}
ตรงกันข้ามกับตัวอย่างนี้โดยที่เราใช้การตั้งค่าคอมไพเลอร์เดียวกัน แต่ให้ค่าในเวลาคอมไพล์ส่งผลให้การประเมินเวลาคอมไพล์มีความแม่นยำสูงขึ้น