Sau khi một số đào nó trông giống như sử dụng std::initializer_list
là không thể trong GCC 4.7 do thiếu constexpr
trong việc kê khai của nó. Nó nên hoạt động với GCC 4.8 là <initializer_list>
đã được cập nhật để bao gồm constexpr
. Thật không may bằng cách sử dụng GCC 4.8 không phải là một lựa chọn tại thời điểm này.
Có thể truy cập các phần tử của một mảng nếu con trỏ bị phân rã được truyền qua tham chiếu. Điều này cho phép xác thực xảy ra như mong muốn nhưng vẫn không hoàn toàn là giải pháp mà tôi hy vọng. Mã sau đây là một giải pháp khả thi cho các mảng. Nó vẫn yêu cầu kích thước của mảng được cung cấp cho hàm xác nhận nhưng nó đủ dễ sửa.
#include <initializer_list>
template<typename T>
constexpr bool Compare(T& data, int size, int needleIndex, int haystackIndex)
{
return
needleIndex == haystackIndex ?
Compare(data, size, needleIndex + 1, haystackIndex)
: needleIndex == size ?
false
: data[needleIndex] == data[haystackIndex] ?
true
: Compare(data, size, needleIndex + 1, haystackIndex);
}
template<typename T>
constexpr bool Compare(T& data, int size, int index)
{
return
index == size ?
false
: Compare(data, size, index + 1) ?
true
: Compare(data, size, 0, index);
}
template<typename T, int ArraySize>
constexpr bool Validate(T(&input)[ArraySize], int size)
{
return !Compare(input, size, 0);
}
int main()
{
constexpr int initData0[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
constexpr int initData1[] = {1, 1, 2, 3, 4, 5, 6, 7, 8, 9};
constexpr int initData2[] = {2, 1, 2, 3, 4, 5, 6, 7, 8, 9};
constexpr int initData3[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 8};
constexpr int initData4[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 7};
constexpr int initData5[] = {0, 1, 0, 3, 4, 5, 6, 7, 8, 9};
constexpr int initData6[] = {0, 1, 2, 3, 4, 5, 6, 9, 8, 9};
static_assert(Validate(initData0, 10), "set 0 failed"); // <-- PASS
static_assert(Validate(initData1, 10), "set 1 failed"); // <-- (and below) FAIL
static_assert(Validate(initData2, 10), "set 2 failed");
static_assert(Validate(initData3, 10), "set 3 failed");
static_assert(Validate(initData4, 10), "set 4 failed");
static_assert(Validate(initData5, 10), "set 5 failed");
static_assert(Validate(initData6, 10), "set 6 failed");
}
.
Build log:
C:\Source\SwitchCaseString\main.cpp: In function 'int main()':
C:\Source\SwitchCaseString\main.cpp:198:2: error: static assertion failed: set 1 failed
C:\Source\SwitchCaseString\main.cpp:199:2: error: static assertion failed: set 2 failed
C:\Source\SwitchCaseString\main.cpp:200:2: error: static assertion failed: set 3 failed
C:\Source\SwitchCaseString\main.cpp:201:2: error: static assertion failed: set 4 failed
C:\Source\SwitchCaseString\main.cpp:202:2: error: static assertion failed: set 5 failed
C:\Source\SwitchCaseString\main.cpp:203:2: error: static assertion failed: set 6 failed
Theo đề xuất hiện tại cho [C++ 14] (http://isocpp.org/files/papers/N3690.pdf), 'bắt đầu()' và ' end() 'của' std :: initializer_list' sẽ là 'constexpr' trong tương lai (xem 18.9/1). Điều đó loại bỏ một trở ngại, nhưng tôi không chắc chắn liệu dereferencing các giá trị lặp sẽ bao giờ có thể tại thời gian biên dịch. – jogojapan
@jogojapan: Các "trình lặp" của một 'std :: initializer_list' chỉ là 'T *' - được bảo đảm. –
Xeo
@Xeo Có, và tôi giả định rằng dereferencing như một con trỏ sẽ không được phép trong một biểu thức liên tục. – jogojapan