2016-01-02 14 views
15

Chương trình sau biên dịch với GCC 5.2, nhưng không phải với kêu vang 3.6:là thông báo lỗi này đúng: không kiểu mẫu lập luận không phải là một biểu thức hằng

constexpr bool flag(); 

template <bool b = flag()> 
constexpr bool test() 
{ 
    return b; 
} 

int main() 
{ 
} 

Thông báo lỗi tôi nhận được với kêu vang là:

main.cpp:3:20: error: non-type template argument is not a constant expression 
template <bool b = flag()> 
        ^~~~~~ 
main.cpp:3:20: note: undefined function 'flag' cannot be used in a constant expression 
main.cpp:1:16: note: declared here 
constexpr bool flag(); 
      ^
main.cpp:4:16: error: no return statement in constexpr function 
constexpr bool test() 
      ^

Câu hỏi của tôi là: Ai là đúng? Hay nói cách khác: Chương trình có hình thành không?

+1

Có thể xác nhận điều này, thậm chí cả tiếng kêu 3.7 không biên dịch nó. Tuy nhiên, nếu bạn đặt câu lệnh return vào 'constexpr bool flag()', nó hoạt động. – vsoftco

+1

Tôi nghĩ rằng điều này liên quan đến câu hỏi khác của bạn về điểm mà đối số mẫu mặc định được đánh giá: Nếu chúng được đánh giá tại điểm định nghĩa, thì clang không thể chứng minh rằng mẫu này không đúng định dạng trong [temp.res] p8 – dyp

+0

bạn có câu lệnh return trong hàm void không? Tôi cũng có thể xác nhận rằng điều này biên dịch trên MSVS 2015 – NathanOliver

Trả lời

4

Tôi muốn nói vang đó là đúng:

Từ Tiêu chuẩn:

[temp.param] 14,1 # 9

9 Một mặc định mẫu đối số là một mẫu đối số (14.3) được chỉ định sau = trong tham số mẫu. [...]

Và [temp.arg.nontype] 14.3.2

1 Mẫu đối số cho một tổ chức phi kiểu mẫu tham số phải là một biểu thức hằng số chuyển đổi (5.20) của loại tham số mẫu.

Và [expr.const] 5,20

2 Một điều kiện thể hiện e là một biểu thức hằng lõi trừ khi việc đánh giá e, theo các quy tắc của máy trừu tượng (1.9), sẽ đánh giá một của các biểu thức sau:

[...]

(2.3) - một yêu cầu của một hàm constexpr không xác định hoặc một hàm tạo constexpr không xác định;

flag() được khai báo nhưng không được xác định, nó không phải là biểu thức không đổi và 14.3.2 bị vi phạm.

4

Theo ISO C++ 14 Chuẩn 5.19.2:

Một điều kiện thể hiện e là một biểu thức hằng lõi trừ khi đánh giá của e, theo các quy tắc của máy trừu tượng (1.9), sẽ đánh giá một trong các biểu thức sau:

  • điều này (5.1.1), ngoại trừ hàm constexpr hoặc hàm tạo constexpr đang được đánh giá là một phần của e;
  • yêu cầu hàm khác không phải là hàm tạo constexpr cho lớp chữ, hàm constexpr hoặc lời gọi ngầm của hàm hủy nhỏ (12.4) [Lưu ý: Độ phân giải quá tải (13.3) được áp dụng như lưu ý cuối cùng] ;
  • yêu cầu hàm constexpr không xác định hoặc hàm tạo constexpr không xác định;
  • (...) Blockquote

Kết quả của bất kỳ cuộc gọi chức năng constexpr thực hiện trước khi nó định nghĩa không phải là một biểu thức hằng.

Cuối cùng có vẻ như đó là lỗi GCC.

+2

Tôi nghĩ mọi người đều đồng ý về điều đó. Có một số câu hỏi bổ sung mặc dù, một trong những chính có lẽ là: là clang được phép từ chối chương trình này * mặc dù các đối số mẫu mặc định là không bao giờ được sử dụng *? – dyp

+0

@ FilipRoséen-refp Tôi biết bạn phải giải quyết vấn đề này cho kỹ thuật smeta của bạn, nhưng tôi không thể nhớ thông tin này đến từ đâu. Là nó từ một dự thảo, thảo luận, báo cáo lỗi, ..? – dyp

+0

@dyp Tôi khá chắc chắn rằng tôi giải quyết từ ngữ cụ thể trong một trong các bài đăng tại http://b.atch.se - Tôi hiện đang ở trên tàu điện ngầm nhưng có thể cung cấp chi tiết về vấn đề này (bao gồm cả câu trả lời) khi tôi về nhà (hy vọng). –

Các vấn đề liên quan