2015-10-18 30 views
5

Đây là những gì tôi đã có:Có thể một lớp C++ chứa một const std tĩnh :: mảng khởi tạo nội tuyến trong một tệp tiêu đề không?

struct Foo 
{ 
    static std::array<double, 4> acgt_default_background_frequencies() { return {0.281774, 0.222020, 0.228876, 0.267330}; } 
}; 

Nhưng tôi muốn không sử dụng một hàm và thay vào đó chỉ có một biến, như thế này:

struct Foo 
{ 
    static constexpr std::array<double, 4> acgt_default_background_frequencies = {0.281774, 0.222020, 0.228876, 0.267330}; 
}; 

Những gì tôi muốn biên dịch , nhưng khi tôi try to useFoo::acgt_default_background_frequencies nó cung cấp cho lỗi trình liên kết "không xác định tham chiếu đến` Foo :: acgt_default_background_frequencies '".

Tôi đang cố gắng làm điều gì? Tôi nghĩ rằng nó là rõ ràng hơn cho người đọc của tiêu đề của tôi nếu tôi có giá trị inlined như một const hơn để ẩn nó trong tập tin .cpp và có một hằng số như trái ngược với một chức năng cũng có vẻ rõ ràng hơn. Không phải là điểm của constexpr để cho phép các công cụ như thế này? Nếu không thể, tại sao không?

+0

Cách tiếp cận chức năng của bạn không hiệu quả vì nó sao chép toàn bộ mảng mỗi khi được gọi. Bạn có thể sửa lỗi này bằng cách làm cho mảng tĩnh và trả về một tham chiếu đến nó. –

Trả lời

6

gì bạn có trong ví dụ thứ hai là một tuyên bố của một thành viên static dữ liệu trong đó có một khởi tạo, nhưng bạn chưa cung cấp một định nghĩa bất cứ nơi nào. Nếu bạn thực hiện odr-use của thành viên đó, một định nghĩa sẽ được yêu cầu.

Để cung cấp một định nghĩa, thêm dòng sau vào tập tin cpp của bạn

constexpr std::array<double, 4> Foo::acgt_default_background_frequencies; 

Việc kê khai trong câu hỏi hoạt động trong C++ 14, nhưng lưu ý rằng trong C++ 11 bạn cần thêm một bộ dấu ngoặc nhọn, ví dụ

struct Foo 
{ 
    static constexpr std::array<double, AlphabetSize> acgt_default_background_frequencies = {{0.281774, 0.222020, 0.228876, 0.267330}}; 
}; 

Các standardese có liên quan từ N3337 §9.4.2/3 [class.static.data]

... Một thành viên static dữ liệu loại đen có thể được khai báo trong định nghĩa lớp với thông số constexpr; nếu vậy, khai báo của nó phải chỉ định bộ khởi tạo dấu ngoặc đơn hoặc bằng nhau, trong đó mỗi mệnh đề khởi tạo là một biểu thức chuyển nhượng là một biểu thức không đổi. ... Thành viên vẫn sẽ được xác định trong phạm vi không gian tên nếu nó được sử dụng không đúng (3.2) trong chương trình và định nghĩa phạm vi không gian tên không chứa bộ khởi tạo .

+1

Có bao nhiêu bản sao của mảng trong chương trình cuối cùng? –

+0

Cảm ơn các công trình, nhưng tôi vẫn còn bối rối tại sao 'static constexpr std :: array ' cần định nghĩa trong tệp .cpp trong khi 'static constexpr double' thì không. – JDiMatteo

+0

@NeilKirk Sẽ chỉ có một 'Foo :: acgt_default_background_frequencies', giống như bất kỳ thành viên dữ liệu tĩnh nào khác. – Praetorian

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