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
và
// m1.cpp
#include "foo.hpp"
int m1() {
return bar();
}
//EOF
và
// 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.cpp
và m2.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ố m1
và m2
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.
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 :) –