typedef enum colors {
MIN_COLOR,
RED = MIN_COLOR,
GREEN,
MAX_COLOR
} colors;
template< colors C >
struct MapEntry {
std::string s;
MapEntry(std::string s_):s(s_) {}
};
void do_in_order() {}
template<typename F0, typename... Fs>
void do_in_order(F0&& f0, Fs&&... fs) {
std::forward<F0>(f0)();
do_in_order(std::forward<Fs>(fs)...);
}
struct MapInit {
std::map< std::string, color > retval;
operator std::map< std::string, color >() {
return std::move(retval);
}
template<colors C>
void AddToMap(MapEntry<C>&& ent) {
retval.insert(std::make_pair(std::move(end.s), C));
}
template< typename... Entries >
MapInit(Entries&& entries) {
do_in_order([&](){ AddToMap(entries); }...);
}
};
template<typename... Entries>
MapInit mapInit(Entries&&... entries) {
return MapInit(std::forward<Entries>(entries)...);
}
const std::map<std::string, colors> = mapInit(MapEntry<RED>("red"), MapEntry<GREEN>("green"));
mang đến cho bạn một cách C++ 11 để xây dựng một std::map
từ thời gian biên dịch color
và thời gian chạy string
dữ liệu.
Ném vào "danh sách MapEntry<colors>
vào danh sách colors
" tính năng tiếp theo.
template<colors... Cs>
struct color_list {};
template<typename... Ts>
struct type_list {};
template<typename MapEnt>
struct extract_color;
template<colors C>
struct extract_color<MapEntry<C>> {
enum {value=C};
};
template<typename Entries>
struct extract_colors;
template<typename... MapEntries>
struct extract_colors<type_list<MapEntries...>> {
typedef color_list< ((colors)extract_colors<MapEntries>::value)... > type;
};
Sắp xếp danh sách đó. Phát hiện các bản sao - nếu có, bạn đã làm hỏng.
Sắp xếp thời gian biên dịch khó hơn phần còn lại của điều này và hơn 100 dòng mã. Tôi sẽ bỏ nó ra nếu bạn không nhớ quá nhiều! Here is a compile time merge sort I wrote in the past to answer a stack overflow question sẽ hoạt động với sự thích nghi tương đối đơn giản (nó sắp xếp các loại với các giá trị, trong trường hợp này chúng tôi sắp xếp một danh sách các giá trị thời gian biên dịch trực tiếp).
// takes a sorted list of type L<T...>, returns true if there are adjacent equal
// elements:
template<typename clist, typename=void>
struct any_duplicates:std::false_type {};
template<typename T, template<T...>class L, T t0, T t1, T... ts>
struct any_duplicates< L<t0, t1, ts...>, typename std::enable_if<t0==t1>::type>:
std::true_type {};
template<typename T, template<T...>class L, T t0, T t1, T... ts>
struct any_duplicates< L<t0, t1, ts...>, typename std::enable_if<t0!=t1>::type>:
any_duplicates< L<t1, ts...> > {};
Phát hiện các yếu tố bên ngoài phạm vi hợp lệ colors
(ví dụ, <MIN_COLOR
hoặc >=MAX_COLOR
). Nếu vậy, bạn đã bị hỏng.
template<typename List>
struct min_max;
template<typename T, template<T...>class L, T t0>
struct min_max {
enum {
min = t0,
max = t1,
};
};
template<typename T, template<T...>class L, T t0, T t1, T... ts>
struct min_max {
typedef min_max<L<t1, ts...>> rest_of_list;
enum {
rest_min = rest_of_list::min,
rest_max = rest_of_list::max,
min = (rest_min < t0):rest_min:t0,
max = (rest_max > t0):rest_max:t0,
};
};
template< typename T, T min, T max, typename List >
struct bounded: std::integral_constant< bool,
(min_max<List>::min >= min) && (min_max<List>::max < max)
> {};
Đếm số lượng phần tử - cần có MAX_COLOR
yếu tố. Nếu không, bạn hơi say.
template<typename List>
struct element_count;
template<typename T, template<T...>L, T... ts>
struct element_count<L<ts...>>:std::integral_constant< std::size_t, sizeof...(ts) > {};
Nếu không ai trong số này xảy ra, bởi pigeonhole bạn phải đã khởi tạo mỗi người trong số họ.
Điều duy nhất còn thiếu là bạn có thể đã tắt và sử dụng cùng một string
cho hai giá trị.Khi biên dịch thời gian string
s là một nỗi đau, chỉ cần kiểm tra điều này tại thời gian chạy (số lượng các mục trong map
bằng số lượng colors
sau khi bạn khởi tạo nó).
Làm điều này trong C++ 03 sẽ khó hơn. Bạn thiếu các mẫu biến dạng, vì vậy bạn sẽ phải giả mạo chúng. Đó là một nỗi đau. mpl
có thể giúp bạn ở đó.
Mẫu biến thể có sẵn trong bản cập nhật trình biên dịch MSVC CTP tháng 11 năm 2012.
Dưới đây là ví dụ về đồ chơi mà không cần kiểm tra trùng lặp và không kiểm tra giới hạn (nó chỉ kiểm tra số lượng mục khớp với bản đồ);
#include <cstddef>
#include <utility>
#include <string>
#include <map>
enum TestEnum {
BeginVal = 0,
One = BeginVal,
Two,
Three,
EndVal
};
template<TestEnum e>
struct MapEntry {
enum { val = e };
std::string s;
MapEntry(std::string s_):s(s_) {}
};
void do_in_order() {}
template<typename F0, typename... Fs>
void do_in_order(F0&& f0, Fs&&... fs) {
std::forward<F0>(f0)();
do_in_order(std::forward<Fs>(fs)...);
}
template<typename... MapEntries>
struct count_entries:std::integral_constant< std::size_t, sizeof...(MapEntries) > {};
// should also detect duplicates and check the range of the values:
template<typename... MapEntries>
struct caught_them_all:
std::integral_constant<
bool,
count_entries<MapEntries...>::value == (TestEnum::EndVal-TestEnum::BeginVal)
>
{};
struct BuildMap {
typedef std::map<std::string, TestEnum> result_map;
mutable result_map val;
operator result_map() const {
return std::move(val);
}
template<typename... MapEntries>
BuildMap(MapEntries&&... entries) {
static_assert(caught_them_all<MapEntries...>::value, "Missing enum value");
bool _[] = { ((val[ entries.s ] = TestEnum(MapEntries::val)), false)... };
}
};
std::map< std::string, TestEnum > bob = BuildMap(
MapEntry<One>("One")
,MapEntry<Two>("Two")
#if 0
,MapEntry<Three>("Three")
#endif
);
int main() {}
Thay thế #if 0
bằng #if 1
để xem nó biên dịch. Live link nếu bạn muốn chơi.
Bạn kiểm tra mã của bạn trước khi vận chuyển, phải không? Vì vậy, kiểm tra thời gian chạy sẽ là đủ để đảm bảo nó hoạt động, bạn có nghĩ vậy không? –
Cấu trúc ngôn ngữ duy nhất mà tôi biết sẽ cảnh báo bạn nếu bạn bỏ lỡ một giá trị enum là 'switch' nếu bạn thêm' case' cho mỗi giá trị và bạn không có nhánh 'default'. Tôi đoán điều này có nghĩa là bạn sẽ cần một vĩ mô nhưng tôi xa đề xuất bất cứ điều gì cụ thể :) –
Tôi đồng ý rằng thời gian chạy thử nghiệm là đủ, và tôi cũng biết về cảnh báo. Tôi nghĩ rằng tôi chỉ cố gắng tìm ra cách xa này có thể được đẩy ra – FKaria