2015-08-09 30 views
23

Tại sao tôi có thể làm điều này:đột biến một int bên trong một hàm constexpr

constexpr auto i_can() { 
    int a = 8; 
    a = 9; 
    //... 
} 

Nhưng tôi không thể làm điều này:

constexpr auto i_cannot() { 
    std::array<int, 10> arr{}; 
    //I cannot 
    arr[5] = 9; 
} 

Câu hỏi của tôi là:

  1. Nếu tôi có thể đột biến một số int, tại sao tôi không thể biến đổi một số int nằm trong mảng?
  2. Đây có phải là giới hạn ngôn ngữ (C++ 14) hoặc một vấn đề về thư viện chuẩn không? reference std::array<T, N>::operator[](size_t) hiện không phải là constexpr.
+5

Liên quan: [LWG issue 2243] (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#2443) – dyp

Trả lời

16

Đây là một hạn chế của thư viện tiêu chuẩn kể từ khi bạn thể sửa đổi một mảng C đơn giản trong một constexpr:

#include <iostream> 

constexpr auto demo() 
{ 
    int arr[10] = {}; 
    arr[5] = 9; 
    return arr[5]; 
} 

int main() 
{ 
    static_assert(demo() == 9, ""); 
    std::cout << demo() << std::endl; 
    return 0; 
} 

DEMO

đầu ra

9 

tôi f bạn đã thêm constexpr vào operator[] của việc triển khai array, bạn cũng có thể sử dụng toán tử này bên trong một constexpr.

DEMO

+2

Đây có phải là một câu trả lời hay câu trả lời? – Shoe

+0

Mã của bạn không chứng minh rằng 'demo' đang tạo ra một biểu thức liên tục khi được gọi. Bạn sẽ phải viết ví dụ 'static_assert (demo() == 9," ");' để chắc chắn. – Columbo

+0

@Columbo cảm ơn cho gợi ý, tôi đã thêm 'static_assert' –

17

Modification của các đối tượng bên trong constexpr chức năng đã được giới thiệu với C++ 14. Tuy nhiên, trong khi sửa đổi, ví dụ: một vô hướng bởi một nhiệm vụ là tốt, việc sửa đổi một đối tượng lớp thông qua một hàm thành viên vẫn cần hàm thành viên đó là constexpr. Và không may, như bạn đã đề cập, thông số hiện tại std::array không khai báo số không constoperator[]constexpr.
Do đó, §7.1.5/5 làm cho định nghĩa của bạn vô hình thành:

Đối với một tổ chức phi-mẫu, không vỡ constexpr chức năng [...], nếu không có giá trị đối số tồn tại như vậy mà một lời gọi của chức năng […] có thể là một biểu diễn được đánh giá của biểu thức hằng số lõi (5.20), […], chương trình bị hỏng; không cần chẩn đoán.

Bạn có thể tạm thời sử dụng triển khai hiện đại hơn nếu bạn muốn đầy đủ constexpr -ness. Ví dụ. Constainer::Array.

+0

để nó xảy ra tương tự với bitet: ( –

+2

@ GermánDiago Vâng, sử dụng ['Constainer :: Bitset'] (https://github.com/Arcoth/Constainer/blob/master/Bitset.hxx) :-P – Columbo

+2

Chỉ cần một quan sát, "constainer" thực sự là tên của thư viện Columbo đề cập đến, và không phải là lỗi chính tả. –

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