2011-10-31 38 views
13

Tôi có vi phạm Quy tắc một định nghĩa với chương trình sau không?không gian tên ẩn danh và quy tắc một định nghĩa

// foo.hpp 
#ifndef FOO_HPP_ 
#define FOO_HPP_ 

namespace { 
    inline int foo() { 
     return 1; 
    } 
} 

inline int bar() { 
    return foo(); 
} 
#endif 
//EOF 

// m1.cpp 

#include "foo.hpp" 

int m1() { 
    return bar(); 
} 

//EOF 

// m2.cpp 

#include "foo.hpp" 

int m2() { 
    return bar(); 
} 

//EOF 

và cuối cùng

// main.cpp 
#include <iostream> 

int m1(); 
int m2(); 

int main(int, const char* []) 
{ 
    int i = m1(); 
    int j = m2(); 

    std::cout << (i+j) << std::endl; 
    return 0; 
} 

// EOF 

Ở phía trên, lưu ý rằng foo() được định nghĩa trong một không gian tên vô danh, vì vậy tôi hy vọng rằng mỗi đơn vị dịch m1.cppm2.cpp sẽ có phiên bản riêng, do đó không có vi phạm ODR. Mặt khác, bar() chỉ là chức năng nội tuyến cũ đơn giản diễn ra để gọi 2 số khác nhau foo s. Vì vậy, nó vi phạm ODR, phải không?

Cập nhật: Trước đây tôi đã có macro trong định nghĩa của foo làm thay đổi giá trị của nó đã trở lại và mỗi người trong số m1m2 xác định vĩ mô khác nhau trước khi đưa foo.hpp. (Và với ví dụ trước đó, g++ sẽ tạo ra một mã nhị phân xuất ra (i+j) với một giá trị khác với những gì bạn mong đợi.) Nhưng thực tế chương trình này vi phạm ODR ngay cả khi phần thân của foo() giống hệt nhau.

+5

Tôi nghĩ điều này minh họa rõ ràng lý do tại sao sử dụng các không gian tên ẩn danh hoặc các hàm tĩnh trong các tệp tiêu đề mang lại những rắc rối :) –

Trả lời

7

Điều này vi phạm ODR. Xem 3.2/5 được nói về chức năng extern inline (bar):

trong mỗi định nghĩa của D, tên tương ứng, ngẩng đầu lên theo 3.4, sẽ đề cập đến một thực thể được xác định trong định nghĩa của D, hoặc sẽ tham chiếu đến cùng một pháp nhân ...

đề cập đến hai phiên bản khác nhau của foo, do đó vi phạm quy tắc.

6

Có, định nghĩa này của bar() vi phạm Quy tắc một định nghĩa. Bạn đang tạo nhiều định nghĩa, mỗi định nghĩa gọi một hàm khác được gọi là foo().

Như bạn nói, nó sẽ là một sự vi phạm ngay cả khi tất cả các phiên bản của foo() là giống nhau, vì chúng vẫn là các chức năng khác nhau.

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