2016-06-02 21 views
15

GCC v6.1 (kết quả là cùng với v5.1) thành công biên dịch mã bên dưới với cờ -std=c++11 -Wall -Wextra -Wpedantic, nhưng tạo ra cảnh báo này:Tại sao biên dịch với C++ 11 là thành công mặc dù sử dụng tính năng C++ 14?

variable templates only available with -std=c++14 or -std=gnu++14 

Mã:

#include <iostream> 

template <typename T> 
struct ParamMetadata { 
     T min; 
     T max; 
}; 

template <class T1, class T2> 
class FooMap {}; 

template <typename T> 
// WARNING PRODUCED ON THIS LINE 
extern FooMap<int, ParamMetadata<T> > metadataHashmap; 

int main() { 
     return 0; 
} 

Clang v3 .8 đưa ra cảnh báo tương tự:

variable templates are a C++14 extension [-Wc++14-extensions] 

Nếu đây là tính năng chỉ có sẵn trong C++ 14, tại sao nó biên dịch với cờ C++ 11 tốt và tôi c một chạy thực thi? Nó không phải là một lỗi nghiêm trọng sao?

+3

Sử dụng '-nhập lỗi 'cho lỗi –

+0

@PiotrSkotnicki Chắc chắn, nhưng chương trình quản lý được xây dựng và chạy mà không có tính năng bắt buộc như thế nào? – DBedrenko

+1

Tại sao bạn nghĩ nó chạy mà không có tính năng cần thiết? –

Trả lời

12

Tiêu chuẩn C++ không có khái niệm về "lỗi trình biên dịch gây tử vong". Các chương trình được hình thành không đúng với chẩn đoán bắt buộc, hoặc hình thành bệnh không cần chẩn đoán hoặc được hình thành tốt.

Trong C++, yêu cầu duy nhất các địa điểm chuẩn trên chẩn đoán chương trình không đúng định dạng là hiển thị chẩn đoán . Nội dung của chẩn đoán đó không được xác định. Điều gì khác xảy ra ngoài chẩn đoán đó không được xác định.

Nhiều trình biên dịch triển khai các phần mở rộng tới tiêu chuẩn C++, chúng được yêu cầu biên dịch dựa vào các chương trình không có hình thức khác và tạo ra một tệp thực thi có thể chạy được. Nếu chúng tuân thủ một tiêu chuẩn, điều duy nhất chúng phải làm là in một thông báo cảnh báo (đáp ứng yêu cầu chẩn đoán của (các) chuẩn C++).

Trong trường hợp này, nó đang in thông báo cảnh báo mà bạn đã sử dụng tính năng C++ 14. Nó bây giờ đã thực hiện thành công những gì mà tiêu chuẩn C++ 11 yêu cầu với chương trình hình thành của bạn. Nó cũng tạo ra một tệp thực thi mà chương trình của bạn sẽ làm gì nếu tính năng đó từ tiêu chuẩn C++ 14 đã được sử dụng: nó là miễn phí để làm như vậy, vì tiêu chuẩn tại thời điểm này không hạn chế những gì chương trình thực hiện một khi nó là một chương trình C++ 11 không thành công.

Nếu bạn không muốn tùy chọn này, trình biên dịch thường có cờ warnings-as-errors và các cờ khác nhau strictpedantic chặn các tiện ích mở rộng theo tiêu chuẩn mà chúng sử dụng. Sau đó, lỗi sẽ ngăn chặn việc tạo ra tệp thực thi và bạn sẽ không còn bị nhầm lẫn nữa.

gcc theo mặc định giả định bạn thực sự muốn biên dịch mã được cung cấp thành thứ gì đó, chứ không phải là hành động chuẩn, và chỉ tạo ra lỗi khi không có cách hợp lý để diễn giải mã của bạn như một chương trình có thể khớp với ý định của bạn . Nó cung cấp cờ để chuyển nó sang một chế độ nghiêm ngặt và pedantic.


amusingly, in ra một nhân vật không gian duy nhất đáp ứng các yêu cầu để hiển thị một chẩn đoán.Tiêu chuẩn C++ có thể được đọc theo các cách bệnh lý để tạo ra chất lượng thực thi kém trong trình biên dịch của bạn: tạo ra một tiêu chuẩn chống trình biên dịch thù địch không đáng để nỗ lực.

+0

Cảm ơn bạn rất nhiều và tất cả những ai đã trả lời câu hỏi của tôi. Thật là một câu trả lời tuyệt vời! Tôi đã học được rất nhiều về các trình biên dịch ngày nay. Một điều tốt để thêm (đó là giải pháp thực tế cho câu hỏi của tôi) là sử dụng cờ '-pendatic-errors' (kết hợp với' -std = C++ 11 -pedantic'), điều này sẽ khiến trình biên dịch ném một lỗi khi sử dụng tính năng C++ 14. – DBedrenko

+2

"Nó cũng tạo ra tệp thực thi mà chương trình của bạn sẽ làm nếu nó được biên dịch theo tiêu chuẩn C++ 14" - chỉ đối với tính năng cụ thể này: có thể có các phần khác của chương trình vẫn được biên dịch thành công với C++ 11 quy tắc có thể khác trong C++ 14. –

2

Không có gì "phải là lỗi nghiêm trọng". Nếu trình biên dịch viết một thông báo cho bạn biết điều gì đã xảy ra, nó hoàn thành nghĩa vụ của nó.

Bây giờ bạn được tự do đưa ra quyết định đầy đủ về việc có nên xem mã có lỗi nghiêm trọng hay không và thay đổi mã; hoặc đối xử với nó như thể nó là C++ 14 và đi với nó.

Bạn có thể sử dụng công tắc -Werror (thay đổi từ "cảnh báo" thành "lỗi" trong thư) nếu bạn cảm thấy điều đó sẽ hữu ích.

+0

Cảm ơn bạn đã trả lời. Nếu chương trình có thể chạy mà không có tính năng này, thì ý nghĩa của câu hỏi của tôi là thay vào đó hành vi của 'FooMap' khi được biên dịch với C++ 11 là gì? Phần "được thông báo một cách ngớ ngẩn" trong câu trả lời của bạn là câu trả lời rất hữu ích. – DBedrenko

+1

@SpaghettiCat Nó không phải là "chạy mà không có tính năng này". Tính năng này được biên dịch hoàn toàn như thể bạn đang sử dụng '-std = C++ 14'. Sự khác biệt duy nhất là bạn nhận được cảnh báo. – HolyBlackCat

+0

@HolyBlackCat Oh đúng .... vì vậy trình biên dịch buộc sử dụng '-std = C++ 14' khi nó thấy mã là C++ 14 chỉ? Tôi đã không nhận thức được hành vi này ... – DBedrenko

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