enum.cpp
Go to the documentation of this file.
00001 
00002 // enum.cpp: a few simple BOOST_ENUM tests
00003 //
00004 // Copyright 2005 Frank Laub
00005 // Distributed under the Boost Software License, Version 1.0. (See
00006 // accompanying file LICENSE_1_0.txt or copy at
00007 // http://www.boost.org/LICENSE_1_0.txt)
00008 //
00009 
00010 #include <iostream>
00011 #include <iomanip>
00012 #include <functional>
00013 #include <boost/enum.hpp>
00014 #include <boost/concept_check.hpp>
00015 #include <boost/function.hpp>
00016 #include <boost/array.hpp>
00017 #include <boost/type_traits/is_virtual_base_of.hpp>
00018 
00019 using namespace std;
00020 
00021 struct Log
00022 {
00023         BOOST_ENUM_VALUES(Level, const char*,
00024                 (Abort)("unrecoverable problem") 
00025                 (Error)("recoverable problem")   
00026                 (Alert)("unexpected behavior") 
00027                 (Info) ("expected behavior") 
00028                 (Trace)("normal flow of execution") 
00029                 (Debug)("detailed object state listings") 
00030         )
00031 };
00032 
00033 namespace expanded
00034 {
00035         class Level : public boost::detail::enum_base<Level, string>
00036         {
00037         public:
00038                 enum domain
00039                 {
00040                         Abort,
00041                         Error,
00042                         Alert,
00043                         Info,
00044                         Trace,
00045                         Debug,
00046                 };
00047 
00048                 BOOST_STATIC_CONSTANT(index_type, size = 6);
00049 
00050                 Level() {}
00051                 Level(domain index) : boost::detail::enum_base<Level, string>(index) {}
00052 
00053                 typedef boost::optional<Level> optional;
00054                 static optional get_by_name(const char* str)
00055                 {
00056                         if(strcmp(str, "Abort") == 0) return optional(Abort);
00057                         if(strcmp(str, "Error") == 0) return optional(Error);
00058                         if(strcmp(str, "Alert") == 0) return optional(Alert);
00059                         if(strcmp(str, "Info") == 0) return optional(Info);
00060                         if(strcmp(str, "Trace") == 0) return optional(Trace);
00061                         if(strcmp(str, "Debug") == 0) return optional(Debug);
00062                         return optional();
00063                 }
00064 
00065         private:
00066                 friend class boost::detail::enum_base<Level, string>;
00067                 static const char* names(domain index)
00068                 {
00069                         switch(index)
00070                         {
00071                         case Abort: return "Abort";
00072                         case Error: return "Error";
00073                         case Alert: return "Alert";
00074                         case Info: return "Info";
00075                         case Trace: return "Trace";
00076                         case Debug: return "Debug";
00077                         default: return NULL;
00078                         }
00079                 }
00080 
00081                 typedef boost::optional<value_type> optional_value;
00082                 static optional_value values(domain index)
00083                 {
00084                         switch(index)
00085                         {
00086                         case Abort: return optional_value("unrecoverable problem");
00087                         case Error: return optional_value("recoverable problem");
00088                         case Alert: return optional_value("unexpected behavior");
00089                         case Info: return optional_value("expected behavior");
00090                         case Trace: return optional_value("normal flow of execution");
00091                         case Debug: return optional_value("detailed object state listings");
00092                         default: return optional_value();
00093                         }
00094                 }
00095         };
00096 }
00097 
00098 // this macro:
00099 BOOST_ENUM(boolean, 
00100         (False)
00101         (True) 
00102 )
00103 
00104 // expands to this enum model
00105 namespace expanded
00106 {
00107         class boolean : public boost::detail::enum_base<boolean>
00108         {
00109         public:
00110                 enum domain
00111                 {
00112                         False,
00113                         True,
00114                 };
00115 
00116                 BOOST_STATIC_CONSTANT(index_type, size = 2);
00117 
00118         public:
00119                 boolean() {}
00120                 boolean(domain index) : boost::detail::enum_base<boolean>(index) {}
00121 
00122                 typedef boost::optional<boolean> optional;
00123                 static optional get_by_name(const char* str)
00124                 {
00125                         if(strcmp(str, "False") == 0) return optional(False);
00126                         if(strcmp(str, "True") == 0) return optional(True);
00127                         return optional();
00128                 }
00129 
00130         private:
00131                 friend class boost::detail::enum_base<boolean>;
00132                 static const char* names(domain index)
00133                 {
00134                         BOOST_ASSERT(static_cast<index_type>(index) < size);
00135                         switch(index)
00136                         {
00137                         case False: return "False";
00138                         case True: return "True";
00139                         default: return "";
00140                         }
00141                 }
00142         };
00143 }
00144 
00145 // from <winuser.h>
00146 //#define VK_SPACE          0x20
00147 //#define VK_PRIOR          0x21
00148 //#define VK_NEXT           0x22
00149 //#define VK_END            0x23
00150 //#define VK_HOME           0x24
00151 
00152 // this macro:
00153 BOOST_ENUM_VALUES(VirtualKey, int,
00154         (Zero) (0)
00155         (Space)(0x20)
00156         (Prior)(0x21)
00157         (Next) (0x22)
00158         (End)  (0x23)
00159         (Home) (0x24)
00160 )
00161 
00162 // expands to this values model
00163 namespace expanded
00164 {
00165         class VirtualKey : public boost::detail::enum_base<VirtualKey>
00166         {
00167         public:
00168                 enum domain
00169                 {
00170                         Space,
00171                         Prior,
00172                         Next,
00173                         End,
00174                         Home,
00175                 };
00176 
00177                 BOOST_STATIC_CONSTANT(index_type, size = 5);
00178 
00179                 VirtualKey() {}
00180                 VirtualKey(domain index) : boost::detail::enum_base<VirtualKey>(index) {}
00181 
00182                 typedef boost::optional<VirtualKey> optional;
00183                 static optional get_by_name(const char* str)
00184                 {
00185                         if(strcmp(str, "Space") == 0) return optional(Space);
00186                         if(strcmp(str, "Prior") == 0) return optional(Prior);
00187                         if(strcmp(str, "Next") == 0) return optional(Next);
00188                         if(strcmp(str, "End") == 0) return optional(End);
00189                         if(strcmp(str, "Home") == 0) return optional(Home);
00190                         return optional();
00191                 }
00192 
00193         private:
00194                 friend class boost::detail::enum_base<VirtualKey>;
00195                 static const char* names(domain index)
00196                 {
00197                         switch(index)
00198                         {
00199                         case Space: return "Space";
00200                         case Prior: return "Prior";
00201                         case Next: return "Next";
00202                         case End: return "End";
00203                         case Home: return "Home";
00204                         default: return NULL;
00205                         }
00206                 }
00207 
00208                 typedef boost::optional<value_type> optional_value;
00209                 static optional_value values(domain index)
00210                 {
00211                         switch(index)
00212                         {
00213                         case Space: return optional_value(0x20);
00214                         case Prior: return optional_value(0x21);
00215                         case Next: return optional_value(0x22);
00216                         case End: return optional_value(0x23);
00217                         case Home: return optional_value(0x24);
00218                         default: return optional_value();
00219                         }
00220                 }
00221         };
00222 }
00223 
00224 // from <winuser.h>
00225 //#define MK_LBUTTON          0x0001
00226 //#define MK_RBUTTON          0x0002
00227 //#define MK_SHIFT            0x0004
00228 //#define MK_CONTROL          0x0008
00229 //#define MK_MBUTTON          0x0010
00230 
00231 // this macro:
00232 BOOST_BITFIELD(MouseKey, 
00233         (LeftButton)  (0x0001)
00234         (RightButton) (0x0002)
00235         (Shift)       (0x0004)
00236         (Control)     (0x0008)
00237         (MiddleButton)(0x0010)
00238 )
00239 
00240 // expands to this bitfield model
00241 namespace expanded
00242 {
00243         class MouseKey : public boost::detail::bitfield_base<MouseKey>
00244         {
00245         public:
00246                 enum domain
00247                 {
00248                         LeftButton,
00249                         RightButton,
00250                         Shift,
00251                         Control,
00252                         MiddleButton,
00253                 };
00254 
00255                 BOOST_STATIC_CONSTANT(index_type, size = 5);
00256 
00257                 MouseKey() {}
00258                 MouseKey(domain index) : boost::detail::bitfield_base<MouseKey>(index) {}
00259 
00260                 typedef boost::optional<MouseKey> optional;
00261                 static optional get_by_name(const char* str)
00262                 {
00263                         if(strcmp(str, "LeftButton") == 0) return optional(LeftButton);
00264                         if(strcmp(str, "RightButton") == 0) return optional(RightButton);
00265                         if(strcmp(str, "Shift") == 0) return optional(Shift);
00266                         if(strcmp(str, "Control") == 0) return optional(Control);
00267                         if(strcmp(str, "MiddleButton") == 0) return optional(MiddleButton);
00268                         return optional();
00269                 }
00270 
00271         private:
00272                 friend class boost::detail::bitfield_access;
00273                 static const char* names(domain index)
00274                 {
00275                         switch(index)
00276                         {
00277                         case LeftButton: return "LeftButton";
00278                         case RightButton: return "RightButton";
00279                         case Shift: return "Shift";
00280                         case Control: return "Control";
00281                         case MiddleButton: return "MiddleButton";
00282                         default: return NULL;
00283                         }
00284                 }
00285 
00286                 typedef boost::optional<value_type> optional_value;
00287                 static optional_value values(domain index)
00288                 {
00289                         switch(index)
00290                         {
00291                         case LeftButton: return optional_value(0x0001);
00292                         case RightButton: return optional_value(0x0002);
00293                         case Shift: return optional_value(0x0004);
00294                         case Control: return optional_value(0x0008);
00295                         case MiddleButton: return optional_value(0x0010);
00296                         default: return optional_value();
00297                         }
00298                 }
00299         };
00300 
00301         //class WindowStyles
00302         //{
00303         //public:
00304         //      enum domain
00305         //      {
00306         //              Overlapped   = 0x00000000,
00307         //              Popup        = 0x80000000,
00308         //              Child        = 0x40000000,
00309         //              Minimize     = 0x20000000,
00310         //              Visible      = 0x10000000,
00311         //              Disabled     = 0x08000000,
00312         //              ClipSiblings = 0x04000000,
00313         //              ClipChildren = 0x02000000,
00314         //              Maximize     = 0x01000000,
00315         //              Caption      = 0x00C00000,
00316         //              Border       = 0x00800000,
00317         //              DlgFrame     = 0x00400000,
00318         //              VScroll      = 0x00200000,
00319         //              HScroll      = 0x00100000,
00320         //              SysMenu      = 0x00080000,
00321         //              ThickFrame   = 0x00040000,
00322         //              Group        = 0x00020000,
00323         //              TabStop      = 0x00010000,
00324 
00325         //              MinimizeBox  = 0x00020000,
00326         //              MaximizeBox  = 0x00010000,
00327         //      
00328         //              OverlappedWindow = 
00329         //                      Overlapped | 
00330         //                      Caption |
00331         //                      ThickFrame |
00332         //                      MinimizeBox |
00333         //                      MaximizeBox,
00334 
00335         //              Tiled        = Overlapped,
00336         //              Iconic       = Minimize,
00337         //              SizeBox      = ThickFrame,
00338         //              TiledWindow  = OverlappedWindow,
00339         //      };
00340         //};
00341 }
00342 
00343 struct Point
00344 {
00345         Point(int x_, int y_) : x(x_), y(y_) {}
00346         int x;
00347         int y;
00348 };
00349 
00350 ostream& operator << (ostream& os, const Point& rhs)
00351 {
00352         os << rhs.x << ", " << rhs.y;
00353         return os;
00354 }
00355 
00356 bool operator == (const Point& lhs, const Point& rhs)
00357 {
00358         return lhs.x == rhs.x && lhs.y == rhs.y;
00359 }
00360 
00361 BOOST_ENUM_VALUES(Points, Point,
00362         (Origin)(Point(0, 0))
00363         (LeftField)(Point(-100, -100))
00364 )
00365 
00366 template <typename T>
00367 void test_iterator()
00368 {
00369         boost::function_requires<boost::RandomAccessIteratorConcept
00370                 <BOOST_DEDUCED_TYPENAME T::const_iterator> >();
00371 
00372         cout << "iteration begin" << endl;
00373         copy(T::begin(), T::end(), ostream_iterator<T>(cout, "\n"));
00374         cout << "iteration end" << endl;
00375 }
00376 
00377 template <typename T, typename A>
00378 void test_optional_method(
00379         const A& arg, 
00380         const BOOST_DEDUCED_TYPENAME T::optional& expected, 
00381         const char* method_name,
00382         const boost::function1<BOOST_DEDUCED_TYPENAME T::optional, A>& method
00383 )
00384 {
00385         BOOST_DEDUCED_TYPENAME T::optional ret = method(arg);
00386         cout << method_name << "(" << arg << "): ";
00387         if(ret)
00388         {
00389                 BOOST_ASSERT(*ret == *expected);
00390                 cout << *ret << endl;
00391         }
00392         else
00393         {
00394                 BOOST_ASSERT(!expected);
00395                 cout << "failed" << endl;
00396         }
00397 }
00398 
00399 template <typename T>
00400 void test_get_by_name(const std::string& str, const boost::optional<T>& expected)
00401 {
00402         test_optional_method<T, const char*>(str.c_str(), expected, "get_by_name", &T::get_by_name);
00403         if(expected)
00404         {
00405                 stringstream ss;
00406                 ss << str;
00407                 T value;
00408                 ss >> value;
00409 //              cout << "istream: " << value << endl;
00410                 BOOST_ASSERT(value == *expected);
00411         }
00412 }
00413 
00414 template <typename T>
00415 void test_get_by_index(
00416         BOOST_DEDUCED_TYPENAME T::index_type index, 
00417         const boost::optional<T>& expected)
00418 {
00419         test_optional_method<T, BOOST_DEDUCED_TYPENAME T::index_type>(
00420                 index, expected, "get_by_index", &T::get_by_index);
00421 }
00422 
00423 template <typename T>
00424 void test_get_by_value(
00425         BOOST_DEDUCED_TYPENAME T::value_type value, 
00426         const boost::optional<T>& expected)
00427 {
00428         test_optional_method<T, BOOST_DEDUCED_TYPENAME T::value_type>(
00429                 value, expected, "get_by_value", &T::get_by_value);
00430 }
00431 
00432 template <typename T>
00433 void take_enum(const T& value)
00434 {
00435         cout << "take: " << value << endl;
00436 }
00437 
00438 namespace detail
00439 {
00440         template <bool is_enum = false>
00441         struct switch_helper
00442         {
00443                 template <typename T>
00444                 static void apply(const T& value)
00445                 {
00446                         // this is for bitfields
00447                         // it doesn't really make sense to want to switch on a bitfield value
00448                         // therefore, bitfield_base does not have an index() method.
00449                 }
00450         };
00451 
00452         template <>
00453         struct switch_helper<true>
00454         {
00455                 template <typename T>
00456                 static void apply(const T& value)
00457                 {
00458                         cout << "switch(" << value << "): ";
00459                         switch(value.index())
00460                         {
00461                         case 0:
00462                                 cout << "0" << endl;
00463                                 break;
00464                         case 1:
00465                                 cout << "1" << endl;
00466                                 break;
00467                         default:
00468                                 cout << "invalid" << endl;
00469                         }               
00470                 }
00471         };
00472 }
00473 
00474 template <typename T>
00475 struct switch_enum
00476 {
00477         static void apply(const T& value)
00478         {
00479                 typedef BOOST_DEDUCED_TYPENAME T::value_type value_type;
00480                 typedef boost::detail::enum_base<T, value_type> base_type;
00481                 detail::switch_helper<boost::is_base_of<base_type, T>::value>::apply(value);
00482 
00483         }
00484 };
00485 
00486 template <>
00487 struct switch_enum<boolean>
00488 {
00489         static void apply(const boolean& value)
00490         {
00491                 switch(value.index())
00492                 {
00493                 case boolean::True:
00494                         cout << "switch(boolean::True)" << endl;
00495                         break;
00496                 case boolean::False:
00497                         cout << "switch(boolean::False)" << endl;
00498                         break;
00499                 default:
00500                         cout << "switch(boolean::invalid)" << endl;
00501                 }
00502         }
00503 };
00504 
00505 template <>
00506 struct switch_enum<Points>
00507 {
00508         static void apply(const Points& value)
00509         {
00510                 switch(value.index())
00511                 {
00512                 case Points::Origin:
00513                         cout << "switch(Points::Origin)" << endl;
00514                         break;
00515                 case Points::LeftField:
00516                         cout << "switch(Points::LeftField)" << endl;
00517                         break;
00518                 default:
00519                         cout << "switch(Points::invalid)" << endl;
00520                 }
00521         }
00522 };
00523 
00524 template <typename T>
00525 void test_enum(BOOST_DEDUCED_TYPENAME T::value_type invalid_value)
00526 {
00527         boost::function_requires<boost::AssignableConcept<T> >();
00528         boost::function_requires<boost::DefaultConstructibleConcept<T> >();
00529         boost::function_requires<boost::CopyConstructibleConcept<T> >();
00530         boost::function_requires<boost::EqualityComparableConcept<T> >();
00531 
00532         cout << "Testing: " << typeid(T).name() << endl;
00533 
00534         test_iterator<T>();
00535 
00536         cout << "begin: " << *T::begin() << endl;
00537         // the next line causes an expected assertion
00538         //cout << "end: " << *T::end() << endl;
00539 
00540         T invalid;
00541         T first = *T::begin();
00542         T second = T::begin()[1];
00543         T copy = first;
00544         T assign;
00545         assign = first;
00546 
00547         // the next line causes an expected assertion
00548         //cout << "invalid: " << invalid << endl;
00549         cout << "first: " << first << endl;
00550         take_enum(first);
00551         cout << "second: " << second << endl;
00552         cout << "copy: " << copy << endl;
00553         BOOST_ASSERT(copy == first);
00554         cout << "assign: " << assign << endl;
00555         BOOST_ASSERT(assign == first);
00556 
00557         cout << "value(first): " << dec << first.value() << endl;
00558         // the next line causes an expected assertion
00559         //cout << "value(invalid): " << dec << invalid.value() << endl;
00560 
00561         test_get_by_name(first.str(), BOOST_DEDUCED_TYPENAME T::optional(first));
00562         test_get_by_name(second.str(), BOOST_DEDUCED_TYPENAME T::optional(second));
00563         test_get_by_name("foo", BOOST_DEDUCED_TYPENAME T::optional());
00564 
00565         test_get_by_index(0, BOOST_DEDUCED_TYPENAME T::optional(first));
00566         test_get_by_index(T::size, BOOST_DEDUCED_TYPENAME T::optional());
00567         test_get_by_value(first.value(), BOOST_DEDUCED_TYPENAME T::optional(first));
00568         test_get_by_value(invalid_value, BOOST_DEDUCED_TYPENAME T::optional());
00569 
00570         switch_enum<T>::apply(first);
00571         switch_enum<T>::apply(second);
00572 }
00573 
00574 template <typename T>
00575 void test_bitfield(BOOST_DEDUCED_TYPENAME T::value_type invalid_value)
00576 {
00577         test_enum<T>(invalid_value);
00578 
00579         T all_mask(T::all_mask);
00580         T not_mask(T::not_mask);
00581 
00582         cout << hex;
00583         test_get_by_value(all_mask.value(), BOOST_DEDUCED_TYPENAME T::optional(all_mask));
00584         test_get_by_value(not_mask.value(), BOOST_DEDUCED_TYPENAME T::optional());
00585 
00586         T first = *T::begin();
00587         T second = T::begin()[1];
00588         T test;
00589         test |= first;
00590         cout << "test |= first: " << test << endl;
00591 
00592         test |= second;
00593         cout << "test |= second: " << test << endl;
00594 
00595         cout << "all_mask: " << all_mask << endl;
00596         cout << all_mask << " = 0x" << hex << setw(8) << setfill('0') << all_mask.value() << endl;
00597         cout << not_mask << " = 0x" << hex << setw(8) << setfill('0') << not_mask.value() << endl;
00598         cout << "all_mask & first: " << (all_mask & first) << endl;
00599         cout << "first & second: " << (first & second) << endl; 
00600         cout << "first | second: " << (first | second) << endl;
00601         cout << "all_mask[first]: " << all_mask[first] << endl;
00602         cout << "first[second]: " << first[second] << endl;
00603 
00604         T first_set_second = first;
00605         bool ret = first_set_second.set(second);
00606         cout << "first.set(second): " << first_set_second << ", " << ret << endl;
00607         ret = first_set_second.set(second, false);
00608         cout << "first.set(second, false): " << first_set_second << ", " << ret << endl;
00609 
00610 }
00611 
00612 int main(int argc, char* argv[])
00613 {
00614         boolean bFalse = boolean::False;
00615         test_enum<boolean>(-1);
00616         cout << endl;
00617 
00618         test_enum<Log::Level>("foo");
00619         cout << endl;
00620 
00621         test_enum<VirtualKey>(123456789);
00622         cout << endl;
00623 
00624         test_bitfield<MouseKey>(0xffffffff);
00625         MouseKey mkAll = MouseKey::all_mask;
00626         MouseKey mkLeftControl = MouseKey::LeftButton;
00627         mkLeftControl.set(MouseKey::Control);
00628         cout << "mkAll[MouseKey::Control]: " << mkAll[MouseKey::Control] << endl;
00629         cout << "mkLeft.set(MouseKey::Control): " << mkLeftControl << endl;
00630         mkLeftControl.reset(MouseKey::Control);
00631         cout << "mkLeft.reset(MouseKey::Control): " << mkLeftControl << endl;
00632         cout << endl;
00633 
00634         test_enum<expanded::Level>("foo");
00635         cout << endl;
00636 
00637         test_enum<Points>(Point(-1,-1));
00638 
00639         return 0;
00640 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


telekyb_defines
Author(s): Dr. Antonio Franchi and Martin Riedel
autogenerated on Mon Nov 11 2013 11:12:30