2012-09-09 19 views
7

Xét đoạn mã sau:Tại sao constexpr hoạt động với các mẫu?

template<typename T> 
constexpr inline T fma(T a, T b, T c) 
{ 
    return a * b + c; 
} 

này biên dịch tốt. Nhưng tại sao nó? Về lý thuyết, các hàm constexpr chỉ có thể gọi các hàm constexpr khác. Tuy nhiên, không có gì đảm bảo rằng các toán tử sẽ là các hàm constexpr. Ví dụ, giả sử tôi có một số loại với giao diện như sau:

Các nhà khai thác + và * là không constexpr. Nếu tôi viết mã sau:

fma(someType(), someType(), someType()); 

Không nên biên dịch vì hàm constexpr đang gọi hàm không cố định. Nhưng nó chỉ tốt thôi. Tại sao điều này?

Tôi đang sử dụng trình biên dịch G ++ của MinGW với tùy chọn -std = C++ 0x.

+0

Để có ví dụ rõ ràng nó không thể tối ưu hóa mọi thứ, nó biên dịch với GCC 4.7.1 khi ba đối số được nhập vào và kết quả được in: http://ideone.com/aBRPU – chris

+0

hãy thử cách này: 'constexpr someType dummy = fma (someType(), someType(), someType());';) – mfontanini

+0

Ooh, tôi chỉ tìm thấy trong tiêu chuẩn rằng các hàm 'constexpr' là ngầm, nếu điều đó giúp bạn tiết kiệm không gian. – chris

Trả lời

5

Nếu bạn gọi hàm constexpr bằng cách sử dụng các biểu thức không liên tục làm đối số của nó, hàm được thực thi khi chạy.

Nếu bạn làm điều này:

constexpr someType dummy = fma(someType(), someType(), someType()); 

nó sẽ thất bại, vì bạn đang buộc kết quả được lưu trữ trong một loại constexpr. Điều đó không thể được thực hiện trong thời gian biên dịch, do đó bạn nhận được một lỗi biên dịch.

Lưu ý rằng này sẽ công việc nếu bạn cung cấp cả một constructor constexpr và một constexproperator+/* trong someType.

0

Vì mẫu chủ yếu được kiểm tra lỗi khi sử dụng, chỉ khi bạn sử dụng mẫu đó với một loại có toán tử không constexpr, nó sẽ bị lỗi.

5

Từ phần 7.1.5.6 của chuẩn C++ 11:

If the instantiated template specialization of a constexpr function template or member function of a class 
template would fail to satisfy the requirements for a constexpr function or constexpr constructor, that 
specialization is not a constexpr function or constexpr constructor. [ Note: If the function is a member 
function it will still be const as described below. — end note ] If no specialization of the template would 
yield a constexpr function or constexpr constructor, the program is ill-formed; no diagnostic required. 

Điều này có nghĩa rằng một hàm constexpr mẫu làm giảm tới một hàm phi constexpr nếu nó được khởi tạo với các thông số mẫu mà làm cho nó không hàm constexpr hợp lệ.

Nếu nó không phải là một hàm constexpr hợp lệ cho dù bạn tham số gì, thì trình biên dịch có thể khiếu nại, nhưng nó không phải.