2013-02-28 21 views
6

Tôi vừa mới chạy vào một tình huống trong khi chuyên các mẫu mà đã làm cho tôi khó chịu:làm tất cả các trình biên dịch bỏ qua mã mẫu đã tạo khi các chuyên môn rõ ràng có sẵn cho trình liên kết không?

foo.h:

template <class T> 
void foo() { 
    std::cout << "This is the generic foo" << std::endl; 
} 

foo.cc:

#include "foo.h" 
template <> 
void foo<int>() { 
    std::cout << "This is foo<int>" << std::endl; 
} 

main.cc:

#include "foo.h" 

int main() { 
    foo<int>(); 
} 

So. Tôi biên dịch như sau:

g++ -c main.cc 
g++ -c foo.cc 
g++ -o main main.o foo.o 

Đầu ra là "This is foo<int>". Tôi thích đầu ra này. Nhưng tôi lo lắng rằng những gì tôi đang quan sát có thể là duy nhất đối với gcc (tôi không có quyền truy cập vào các trình biên dịch khác để tôi không thể kiểm tra).

Đây là những gì tôi nghĩ rằng gcc đang làm: Khi main.cc được biên dịch, tôi hy vọng nó sẽ phát ra mã chung cho cuộc gọi foo vì nó không biết về chuyên môn trong foo.cc. Nhưng bằng cách liên kết với foo.o, nó sử dụng chuyên môn thay vì nó có cùng chữ ký.

Nhưng điều này có tệ không? Tôi lo lắng rằng các trình biên dịch khác (hoặc thậm chí là các phiên bản khác nhau của gcc?) Có thể mang chữ ký của chúng khi chúng phát ra mã mẫu, theo cách liên kết với foo.o sẽ không thay thế hành động chung như tôi muốn. Đây có phải là một lo lắng hợp lệ? Tôi đã đọc rất nhiều điều khiến tôi cảm thấy khó chịu, nhưng không có gì khiến tôi cảm thấy tự tin về những gì đang xảy ra trong tình hình hiện tại của mình.

+0

Có, bạn không thể dựa vào điều này. Cách di động là chuyển chuyên môn sang tệp .h. –

+1

@HansPassant: bạn không cần phải di chuyển nó, nhưng nó cần phải được biết đến với trình biên dịch (tức là tuyên bố) –

Trả lời

8

Tôi lo lắng rằng những gì tôi đang quan sát có thể là duy nhất đối với gcc (tôi không có quyền truy cập vào các trình biên dịch khác để tôi không thể kiểm tra).

Bạn có lý do chính đáng để lo lắng: Chương trình của bạn không đúng định dạng và trình biên dịch thậm chí không cần phải cho bạn biết!

Đoạn 14.7.3/6 của C++ 11 tiêu chuẩn quy định cụ thể:

Nếu một mẫu, một mẫu thành viên hoặc thành viên của một lớp mẫu được một cách rõ ràng chuyên sau đó rằng chuyên môn hóa phải được khai báo trước khi sử dụng lần đầu tiên chuyên môn hóa mà có thể gây ra một sự diễn giải ngầm định để diễn ra, trong mọi đơn vị dịch thuật trong đó việc sử dụng như vậy xảy ra; không cần chẩn đoán. Nếu chương trình không cung cấp định nghĩa cho chuyên môn rõ ràng và chuyên môn được sử dụng theo cách có thể gây ra hiện tượng ngầm hoặc thành viên là chức năng thành viên ảo, chương trình , không cần chẩn đoán. An instantiation ngầm không bao giờ được tạo ra cho một chuyên môn rõ ràng được khai báo nhưng không được xác định

Chuyên môn của bạn phải được nhìn thấy từ điểm khởi tạo để chương trình có hành vi nhất quán. Trong trường hợp của bạn, nó không phải là: bạn đang xuống hạng nó trong một tập tin mà không được bao gồm bởi các đơn vị dịch thuật khác.

Đoạn 14.7.3/7 tiêu chuẩn là khá rõ ràng về những gì sẽ xảy ra khi bạn không làm điều này:

Các vị trí của tờ khai chuyên môn hóa rõ ràng cho chức năng mẫu, lớp mẫu, chức năng thành viên của các lớp mẫu, [...] , có thể ảnh hưởng đến việc chương trình có phải là được định dạng tốt theo vị trí tương đối của các khai báo chuyên môn rõ ràng và các điểm của chúng là số trong đơn vị dịch như được chỉ định ở trên và bên dưới. Khi viết chuyên môn, hãy cẩn thận về vị trí của nó; hoặc để làm cho nó biên dịch sẽ là một thử nghiệm như để kindle tự thiêu của nó.

Tôi đoán câu cuối cùng làm rõ.

Ở đây, những gì bạn nên làm là tuyên bố ý định của bạn để giới thiệu chuyên môn rõ ràng về mẫu chức năng của bạn trước bất kỳ sự diễn giải tiềm ẩn nào của mẫu chính sẽ xảy ra. Để làm như vậy, làm như sau:

foo.h

template <class T> 
void foo() { 
    std::cout << "This is the generic foo" << std::endl; 
} 

template <> void foo<int>(); // Introduce a declaration of your 
          // explicit specialization right 
          // after you defined the primary 
          // template! 

Bằng việc giới thiệu một tuyên bố ngay sau khi định nghĩa của mẫu ban đầu, bạn hãy chắc chắn rằng bất cứ nơi nào mẫu chính là nhìn thấy, nó sẽ được biết rằng một chuyên môn đầy đủ cho nó tồn tại, tiết kiệm cho bạn từ tự thiêu.

+0

Yêu câu trả lời .. mặc dù đó có thể là phần vui nhộn nhất của tiêu chuẩn, và nên gắn bó với bất kỳ ai bao giờ làm phiền đến rất nhiều khi lướt qua nó. Phần lớn tiêu chuẩn cụ thể được đề cập trong video và thảo luận về tiêu chuẩn như tôi đã lưu ý, nó đã khiến tôi tin tưởng một ai đó đã sử dụng ngôn ngữ đó bất cứ lúc nào. – johnathon

+0

@johnathon: Vâng, đó là một loại từ ngữ bất thường đối với Tiêu chuẩn, nhưng số lượng "WTF" tiềm ẩn vi phạm các quy tắc này có thể gây ra có thể biện minh cho nó. –

+0

lol, ikr, im vẫn cười .... Chủ yếu là, bởi vì tôi có thể nhớ khi tôi đóng góp vào số WTF, lol. – johnathon

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