Đây là một số loại theo dõi cho this topic và đề cập đến một phần nhỏ của nó. Như với chủ đề trước, chúng ta hãy xem xét rằng trình biên dịch của chúng tôi có các hàm constexpr
cho std::initializer_list
và std::array
. Bây giờ, chúng ta hãy đi thẳng vào vấn đề.Lẫn lộn về các biểu thức không đổi
#include <array>
#include <initializer_list>
int main()
{
constexpr std::array<int, 3> a = {{ 1, 2, 3 }};
constexpr int a0 = a[0];
constexpr int a1 = a[1];
constexpr int a2 = a[2];
constexpr std::initializer_list<int> b = { a0, a1, a2 };
return 0;
}
#include <array>
#include <initializer_list>
int main()
{
constexpr std::array<int, 3> a = {{ 1, 2, 3 }};
constexpr std::initializer_list<int> b = { a[0], a[1], a[2] };
return 0;
}
Nó bị treo với lỗi này:
error: 'const std::initializer_list<int>{((const int*)(&<anonymous>)), 3u}' is not a constant expression
Mặc dù tôi đọc một số giấy tờ về constexpr
và thường xuyên biểu trong khi đó, hành vi này vẫn không có ý nghĩa gì đối với tôi. Làm thế nào đến ví dụ đầu tiên được coi là một biểu thức không đổi hợp lệ và không phải là biểu thức thứ hai? Tôi sẽ hoan nghênh mọi lời giải thích để tôi có thể yên nghỉ sau đó.
LƯU Ý: Tôi sẽ chính xác ngay lập tức, Clang sẽ không thể biên dịch đoạn đầu tiên vì nó không thực hiện các bổ sung thư viện constexpr
được lên kế hoạch cho C++ 14. Tôi đã sử dụng GCC 4.7.
EDIT: Ok, ở đây có các ví dụ lớn để hiển thị những gì bị từ chối và những gì không phải là:
#include <array>
#include <initializer_list>
constexpr int foo = 42;
constexpr int bar() { return foo; }
struct eggs { int a, b; };
int main()
{
constexpr std::array<int, 3> a = {{ 1, 2, 3 }};
constexpr int a0 = a[0];
constexpr int a1 = a[1];
constexpr int a2 = a[2];
// From Xeo and Andy tests
constexpr std::array<int, 1> a = { bar() }; // OK
constexpr std::array<int, 3> b = {{ a[0], a[1], a[2] }}; // OK
std::initializer_list<int> b = { a[0], a[1], a[2] }; // OK
constexpr std::initializer_list<int> b = { a0, a1, a2 }; // OK
constexpr std::initializer_list<int> b = { foo }; // OK
constexpr std::initializer_list<int> c = { bar() }; // ERROR
constexpr std::initializer_list<int> b = { a[0], a[1], a[2] }; // ERROR
// From Matheus Izvekov and Daniel Krügler
constexpr eggs good = { 1, 2 }; // OK
constexpr std::initializer_list<eggs> bad = { { 1, 2 }, { 3, 4 } }; // ERROR
constexpr std::initializer_list<eggs> bad2 = { good, good }; // ERROR
return 0;
}
Làm thế nào về "GCC có lỗi"? :) (Không nói nó có một, chỉ là một khả năng.) Và thực sự, bạn sẽ có thể kiểm tra điều này mà không cần bổ sung 'constexpr' bằng cách viết các chất tương tự của riêng bạn. Ngoài ra, còn 'constexpr std :: mảng b = {{a [0], a [1], a [2]}};'? –
Xeo
Có thể [this] (http://ideone.com/56iP0Y) giúp thu hẹp sự cố –
@Xeo Bất cứ điều gì tôi làm với mảng có vẻ hoạt động tốt (bao gồm ví dụ của bạn và Andy chỉ có 'std :: arrays' thay thế của 'std :: initializer_list'). Dường như vấn đề chỉ xảy ra với 'std :: initializer_list' tại thời gian biên dịch. Tôi không quản lý để tái tạo nó mà không có 'constexpr' hoặc với' std :: array'. – Morwenn