variant.hpp 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870
  1. //-----------------------------------------------------------------------------
  2. // boost variant/variant.hpp header file
  3. // See http://www.boost.org for updates, documentation, and revision history.
  4. //-----------------------------------------------------------------------------
  5. //
  6. // Copyright (c) 2002-2003
  7. // Eric Friedman, Itay Maman
  8. //
  9. // Distributed under the Boost Software License, Version 1.0. (See
  10. // accompanying file LICENSE_1_0.txt or copy at
  11. // http://www.boost.org/LICENSE_1_0.txt)
  12. #ifndef BOOST_VARIANT_VARIANT_HPP
  13. #define BOOST_VARIANT_VARIANT_HPP
  14. #include <cstddef> // for std::size_t
  15. #include <new> // for placement new
  16. #if !defined(BOOST_NO_TYPEID)
  17. #include <typeinfo> // for typeid, std::type_info
  18. #endif // BOOST_NO_TYPEID
  19. #include "boost/variant/detail/config.hpp"
  20. #include "boost/mpl/aux_/config/eti.hpp"
  21. #include "boost/mpl/aux_/value_wknd.hpp"
  22. #include "boost/variant/variant_fwd.hpp"
  23. #include "boost/variant/detail/backup_holder.hpp"
  24. #include "boost/variant/detail/enable_recursive_fwd.hpp"
  25. #include "boost/variant/detail/forced_return.hpp"
  26. #include "boost/variant/detail/initializer.hpp"
  27. #include "boost/variant/detail/make_variant_list.hpp"
  28. #include "boost/variant/detail/over_sequence.hpp"
  29. #include "boost/variant/detail/visitation_impl.hpp"
  30. #include "boost/variant/detail/generic_result_type.hpp"
  31. #include "boost/variant/detail/has_nothrow_move.hpp"
  32. #include "boost/variant/detail/move.hpp"
  33. #include "boost/detail/reference_content.hpp"
  34. #include "boost/aligned_storage.hpp"
  35. #include "boost/blank.hpp"
  36. #include "boost/static_assert.hpp"
  37. #include "boost/preprocessor/cat.hpp"
  38. #include "boost/preprocessor/repeat.hpp"
  39. #include "boost/type_traits/alignment_of.hpp"
  40. #include "boost/type_traits/add_const.hpp"
  41. #include "boost/type_traits/has_nothrow_constructor.hpp"
  42. #include "boost/type_traits/has_nothrow_copy.hpp"
  43. #include "boost/type_traits/is_const.hpp"
  44. #include "boost/type_traits/is_same.hpp"
  45. #include "boost/utility/enable_if.hpp"
  46. #include "boost/variant/recursive_wrapper_fwd.hpp"
  47. #include "boost/variant/static_visitor.hpp"
  48. #include "boost/mpl/eval_if.hpp"
  49. #include "boost/mpl/begin_end.hpp"
  50. #include "boost/mpl/bool.hpp"
  51. #include "boost/mpl/not.hpp"
  52. #include "boost/mpl/empty.hpp"
  53. #include "boost/mpl/find_if.hpp"
  54. #include "boost/mpl/front.hpp"
  55. #include "boost/mpl/identity.hpp"
  56. #include "boost/mpl/if.hpp"
  57. #include "boost/mpl/int.hpp"
  58. #include "boost/mpl/is_sequence.hpp"
  59. #include "boost/mpl/iterator_range.hpp"
  60. #include "boost/mpl/iter_fold_if.hpp"
  61. #include "boost/mpl/logical.hpp"
  62. #include "boost/mpl/max_element.hpp"
  63. #include "boost/mpl/next.hpp"
  64. #include "boost/mpl/deref.hpp"
  65. #include "boost/mpl/pair.hpp"
  66. #include "boost/mpl/protect.hpp"
  67. #include "boost/mpl/push_front.hpp"
  68. #include "boost/mpl/same_as.hpp"
  69. #include "boost/mpl/size_t.hpp"
  70. #include "boost/mpl/sizeof.hpp"
  71. #include "boost/mpl/transform.hpp"
  72. #include "boost/mpl/assert.hpp"
  73. ///////////////////////////////////////////////////////////////////////////////
  74. // Implementation Macros:
  75. //
  76. // BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
  77. // Defined in boost/variant/detail/visitation_impl.hpp.
  78. //
  79. // BOOST_VARIANT_MINIMIZE_SIZE
  80. // When #defined, implementation employs all known means to minimize the
  81. // size of variant obje cts. However, often unsuccessful due to alignment
  82. // issues, and potentially harmful to runtime speed, so not enabled by
  83. // default. (TODO: Investigate further.)
  84. #if defined(BOOST_VARIANT_MINIMIZE_SIZE)
  85. # include <climits> // for SCHAR_MAX
  86. # include "boost/mpl/eval_if.hpp"
  87. # include "boost/mpl/equal_to.hpp"
  88. # include "boost/mpl/identity.hpp"
  89. # include "boost/mpl/int.hpp"
  90. # include "boost/mpl/if.hpp"
  91. # include "boost/mpl/less.hpp"
  92. # include "boost/mpl/long.hpp"
  93. # include "boost/mpl/O1_size.hpp"
  94. #endif
  95. namespace boost {
  96. namespace detail { namespace variant {
  97. ///////////////////////////////////////////////////////////////////////////////
  98. // (detail) metafunction max_value
  99. //
  100. // Finds the maximum value of the unary metafunction F over Sequence.
  101. //
  102. template <typename Sequence, typename F>
  103. struct max_value
  104. {
  105. private: // helpers, for metafunction result (below)
  106. typedef typename mpl::transform1<Sequence, F>::type transformed_;
  107. typedef typename mpl::max_element<transformed_
  108. >::type max_it;
  109. public: // metafunction result
  110. typedef typename mpl::deref<max_it>::type
  111. type;
  112. };
  113. ///////////////////////////////////////////////////////////////////////////////
  114. // (detail) metafunction find_fallback_type
  115. //
  116. // Provides a fallback (i.e., nothrow default-constructible) type from the
  117. // specified sequence, or no_fallback_type if not found.
  118. //
  119. // This implementation is designed to prefer boost::blank over other potential
  120. // fallback types, regardless of its position in the specified sequence.
  121. //
  122. class no_fallback_type;
  123. struct find_fallback_type_pred
  124. {
  125. template <typename Iterator>
  126. struct apply
  127. {
  128. private:
  129. typedef typename mpl::deref<Iterator>::type t_;
  130. public:
  131. typedef mpl::not_< has_nothrow_constructor<t_> > type;
  132. };
  133. };
  134. template <typename Types>
  135. struct find_fallback_type
  136. {
  137. private: // helpers, for metafunction result (below)
  138. typedef typename mpl::end<Types>::type end_it;
  139. // [Find the first suitable fallback type...]
  140. typedef typename mpl::iter_fold_if<
  141. Types
  142. , mpl::int_<0>, mpl::protect< mpl::next<> >
  143. , mpl::protect< find_fallback_type_pred >
  144. >::type first_result_;
  145. typedef typename first_result_::first first_result_index;
  146. typedef typename first_result_::second first_result_it;
  147. // [...now search the rest of the sequence for boost::blank...]
  148. typedef typename mpl::iter_fold_if<
  149. mpl::iterator_range< first_result_it,end_it >
  150. , first_result_index, mpl::protect< mpl::next<> >
  151. , mpl::protect< mpl::not_same_as<boost::blank> >
  152. >::type second_result_;
  153. typedef typename second_result_::second second_result_it;
  154. public: // metafunction result
  155. // [...and return the results of the search:]
  156. typedef typename mpl::eval_if<
  157. is_same< second_result_it,end_it >
  158. , mpl::if_<
  159. is_same< first_result_it,end_it >
  160. , mpl::pair< no_fallback_type,no_fallback_type >
  161. , first_result_
  162. >
  163. , mpl::identity< second_result_ >
  164. >::type type;
  165. };
  166. #if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG)
  167. template<>
  168. struct find_fallback_type<int>
  169. {
  170. typedef mpl::pair< no_fallback_type,no_fallback_type > type;
  171. };
  172. #endif // BOOST_MPL_CFG_MSVC_60_ETI_BUG workaround
  173. ///////////////////////////////////////////////////////////////////////////////
  174. // (detail) metafunction make_storage
  175. //
  176. // Provides an aligned storage type capable of holding any of the types
  177. // specified in the given type-sequence.
  178. //
  179. template <typename Types, typename NeverUsesBackupFlag>
  180. struct make_storage
  181. {
  182. private: // helpers, for metafunction result (below)
  183. typedef typename mpl::eval_if<
  184. NeverUsesBackupFlag
  185. , mpl::identity< Types >
  186. , mpl::push_front<
  187. Types, backup_holder<void*>
  188. >
  189. >::type types;
  190. typedef typename max_value<
  191. types, mpl::sizeof_<mpl::_1>
  192. >::type max_size;
  193. #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
  194. typedef typename max_value<
  195. types, alignment_of<mpl::_1>
  196. >::type max_alignment;
  197. #else // borland
  198. // temporary workaround -- use maximal alignment
  199. typedef mpl::size_t< -1 > max_alignment;
  200. #endif // borland workaround
  201. public: // metafunction result
  202. #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
  203. typedef ::boost::aligned_storage<
  204. BOOST_MPL_AUX_VALUE_WKND(max_size)::value
  205. , BOOST_MPL_AUX_VALUE_WKND(max_alignment)::value
  206. > type;
  207. #else // MSVC7 and below
  208. BOOST_STATIC_CONSTANT(std::size_t, msvc_max_size_c = max_size::value);
  209. BOOST_STATIC_CONSTANT(std::size_t, msvc_max_alignment_c = max_alignment::value);
  210. typedef ::boost::aligned_storage<
  211. msvc_max_size_c
  212. , msvc_max_alignment_c
  213. > type;
  214. #endif // MSVC workaround
  215. };
  216. #if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG)
  217. template<>
  218. struct make_storage<int,int>
  219. {
  220. typedef int type;
  221. };
  222. #endif // BOOST_MPL_CFG_MSVC_60_ETI_BUG workaround
  223. ///////////////////////////////////////////////////////////////////////////////
  224. // (detail) class destroyer
  225. //
  226. // Internal visitor that destroys the value it visits.
  227. //
  228. struct destroyer
  229. : public static_visitor<>
  230. {
  231. public: // visitor interfaces
  232. template <typename T>
  233. BOOST_VARIANT_AUX_RETURN_VOID_TYPE
  234. internal_visit(T& operand, int) const
  235. {
  236. operand.~T();
  237. #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551)) || \
  238. BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
  239. operand; // suppresses warnings
  240. #endif
  241. BOOST_VARIANT_AUX_RETURN_VOID;
  242. }
  243. };
  244. ///////////////////////////////////////////////////////////////////////////////
  245. // (detail) class template known_get
  246. //
  247. // Visitor that returns a reference to content of the specified type.
  248. //
  249. // Precondition: visited variant MUST contain logical content of type T.
  250. //
  251. template <typename T>
  252. class known_get
  253. : public static_visitor<T&>
  254. {
  255. #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
  256. public: // visitor interface
  257. T& operator()(T& operand) const
  258. {
  259. return operand;
  260. }
  261. template <typename U>
  262. T& operator()(U&) const
  263. {
  264. // logical error to be here: see precondition above
  265. BOOST_ASSERT(false);
  266. return ::boost::detail::variant::forced_return< T& >();
  267. }
  268. #else // MSVC6
  269. private: // helpers, for visitor interface (below)
  270. T& execute(T& operand, mpl::true_) const
  271. {
  272. return operand;
  273. }
  274. template <typename U>
  275. T& execute(U& operand, mpl::false_) const
  276. {
  277. // logical error to be here: see precondition above
  278. BOOST_ASSERT(false);
  279. return ::boost::detail::variant::forced_return< T& >();
  280. }
  281. public: // visitor interface
  282. template <typename U>
  283. T& operator()(U& operand) const
  284. {
  285. typedef typename is_same< U,T >::type
  286. U_is_T;
  287. return execute(operand, U_is_T());
  288. }
  289. #endif // MSVC6 workaround
  290. };
  291. ///////////////////////////////////////////////////////////////////////////////
  292. // (detail) class copy_into
  293. //
  294. // Internal visitor that copies the value it visits into the given buffer.
  295. //
  296. class copy_into
  297. : public static_visitor<>
  298. {
  299. private: // representation
  300. void* storage_;
  301. public: // structors
  302. explicit copy_into(void* storage)
  303. : storage_(storage)
  304. {
  305. }
  306. public: // internal visitor interface
  307. template <typename T>
  308. BOOST_VARIANT_AUX_RETURN_VOID_TYPE
  309. internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
  310. {
  311. new(storage_) T( operand.get() );
  312. BOOST_VARIANT_AUX_RETURN_VOID;
  313. }
  314. template <typename T>
  315. BOOST_VARIANT_AUX_RETURN_VOID_TYPE
  316. internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
  317. {
  318. new(storage_) T( operand.get() );
  319. BOOST_VARIANT_AUX_RETURN_VOID;
  320. }
  321. template <typename T>
  322. BOOST_VARIANT_AUX_RETURN_VOID_TYPE
  323. internal_visit(const T& operand, int) const
  324. {
  325. new(storage_) T(operand);
  326. BOOST_VARIANT_AUX_RETURN_VOID;
  327. }
  328. };
  329. ///////////////////////////////////////////////////////////////////////////////
  330. // (detail) class assign_storage
  331. //
  332. // Internal visitor that assigns the given storage (which must be a
  333. // constructed value of the same type) to the value it visits.
  334. //
  335. struct assign_storage
  336. : public static_visitor<>
  337. {
  338. private: // representation
  339. const void* rhs_storage_;
  340. public: // structors
  341. explicit assign_storage(const void* rhs_storage)
  342. : rhs_storage_(rhs_storage)
  343. {
  344. }
  345. public: // internal visitor interfaces
  346. template <typename T>
  347. BOOST_VARIANT_AUX_RETURN_VOID_TYPE
  348. internal_visit(backup_holder<T>& lhs_content, long) const
  349. {
  350. lhs_content.get()
  351. = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
  352. BOOST_VARIANT_AUX_RETURN_VOID;
  353. }
  354. template <typename T>
  355. BOOST_VARIANT_AUX_RETURN_VOID_TYPE
  356. internal_visit(const backup_holder<T>& lhs_content, long) const
  357. {
  358. lhs_content.get()
  359. = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
  360. BOOST_VARIANT_AUX_RETURN_VOID;
  361. }
  362. template <typename T>
  363. BOOST_VARIANT_AUX_RETURN_VOID_TYPE
  364. internal_visit(T& lhs_content, int) const
  365. {
  366. // NOTE TO USER :
  367. // Compile error here indicates one of variant's bounded types does
  368. // not meet the requirements of the Assignable concept. Thus,
  369. // variant is not Assignable.
  370. //
  371. // Hint: Are any of the bounded types const-qualified or references?
  372. //
  373. lhs_content = *static_cast< const T* >(rhs_storage_);
  374. BOOST_VARIANT_AUX_RETURN_VOID;
  375. }
  376. };
  377. ///////////////////////////////////////////////////////////////////////////////
  378. // (detail) class direct_assigner
  379. //
  380. // Generic static visitor that: if and only if the visited value is of the
  381. // specified type, assigns the given value to the visited value and returns
  382. // true; else returns false.
  383. //
  384. template <typename T>
  385. class direct_assigner
  386. : public static_visitor<bool>
  387. {
  388. private: // representation
  389. const T& rhs_;
  390. public: // structors
  391. explicit direct_assigner(const T& rhs)
  392. : rhs_(rhs)
  393. {
  394. }
  395. #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
  396. public: // visitor interface
  397. bool operator()(T& lhs)
  398. {
  399. lhs = rhs_;
  400. return true;
  401. }
  402. template <typename U>
  403. bool operator()(U&)
  404. {
  405. return false;
  406. }
  407. #else // MSVC6
  408. private: // helpers, for visitor interface (below)
  409. bool execute(T& lhs, mpl::true_)
  410. {
  411. lhs = rhs_;
  412. return true;
  413. }
  414. template <typename U>
  415. bool execute(U&, mpl::false_)
  416. {
  417. return false;
  418. }
  419. public: // visitor interface
  420. template <typename U>
  421. bool operator()(U& lhs)
  422. {
  423. typedef typename is_same<U,T>::type U_is_T;
  424. return execute(lhs, U_is_T());
  425. }
  426. #endif // MSVC6 workaround
  427. #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
  428. private:
  429. // silence MSVC warning C4512: assignment operator could not be generated
  430. direct_assigner& operator= (direct_assigner const&);
  431. #endif
  432. };
  433. ///////////////////////////////////////////////////////////////////////////////
  434. // (detail) class backup_assigner
  435. //
  436. // Internal visitor that "assigns" the given value to the visited value,
  437. // using backup to recover if the destroy-copy sequence fails.
  438. //
  439. // NOTE: This needs to be a friend of variant, as it needs access to
  440. // indicate_which, indicate_backup_which, etc.
  441. //
  442. template <typename Variant, typename RhsT>
  443. class backup_assigner
  444. : public static_visitor<>
  445. {
  446. private: // representation
  447. Variant& lhs_;
  448. int rhs_which_;
  449. const RhsT& rhs_content_;
  450. public: // structors
  451. backup_assigner(Variant& lhs, int rhs_which, const RhsT& rhs_content)
  452. : lhs_(lhs)
  453. , rhs_which_(rhs_which)
  454. , rhs_content_(rhs_content)
  455. {
  456. }
  457. private: // helpers, for visitor interface (below)
  458. template <typename LhsT>
  459. void backup_assign_impl(
  460. LhsT& lhs_content
  461. , mpl::true_// has_nothrow_move
  462. )
  463. {
  464. // Move lhs content to backup...
  465. LhsT backup_lhs_content(
  466. ::boost::detail::variant::move(lhs_content)
  467. ); // nothrow
  468. // ...destroy lhs content...
  469. lhs_content.~LhsT(); // nothrow
  470. try
  471. {
  472. // ...and attempt to copy rhs content into lhs storage:
  473. new(lhs_.storage_.address()) RhsT(rhs_content_);
  474. }
  475. catch (...)
  476. {
  477. // In case of failure, restore backup content to lhs storage...
  478. new(lhs_.storage_.address())
  479. LhsT(
  480. ::boost::detail::variant::move(backup_lhs_content)
  481. ); // nothrow
  482. // ...and rethrow:
  483. throw;
  484. }
  485. // In case of success, indicate new content type:
  486. lhs_.indicate_which(rhs_which_); // nothrow
  487. }
  488. template <typename LhsT>
  489. void backup_assign_impl(
  490. LhsT& lhs_content
  491. , mpl::false_// has_nothrow_move
  492. )
  493. {
  494. // Backup lhs content...
  495. LhsT* backup_lhs_ptr = new LhsT(lhs_content);
  496. // ...destroy lhs content...
  497. lhs_content.~LhsT(); // nothrow
  498. try
  499. {
  500. // ...and attempt to copy rhs content into lhs storage:
  501. new(lhs_.storage_.address()) RhsT(rhs_content_);
  502. }
  503. catch (...)
  504. {
  505. // In case of failure, copy backup pointer to lhs storage...
  506. new(lhs_.storage_.address())
  507. backup_holder<LhsT>( backup_lhs_ptr ); // nothrow
  508. // ...indicate now using backup...
  509. lhs_.indicate_backup_which( lhs_.which() ); // nothrow
  510. // ...and rethrow:
  511. throw;
  512. }
  513. // In case of success, indicate new content type...
  514. lhs_.indicate_which(rhs_which_); // nothrow
  515. // ...and delete backup:
  516. delete backup_lhs_ptr; // nothrow
  517. }
  518. public: // visitor interface
  519. template <typename LhsT>
  520. BOOST_VARIANT_AUX_RETURN_VOID_TYPE
  521. internal_visit(LhsT& lhs_content, int)
  522. {
  523. typedef typename has_nothrow_move_constructor<LhsT>::type
  524. nothrow_move;
  525. backup_assign_impl( lhs_content, nothrow_move() );
  526. BOOST_VARIANT_AUX_RETURN_VOID;
  527. }
  528. #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
  529. private:
  530. // silence MSVC warning C4512: assignment operator could not be generated
  531. backup_assigner& operator= (backup_assigner const&);
  532. #endif
  533. };
  534. ///////////////////////////////////////////////////////////////////////////////
  535. // (detail) class swap_with
  536. //
  537. // Visitor that swaps visited value with content of given variant.
  538. //
  539. // Precondition: Given variant MUST have same logical type as visited value.
  540. //
  541. template <typename Variant>
  542. struct swap_with
  543. : public static_visitor<>
  544. {
  545. private: // representation
  546. Variant& toswap_;
  547. public: // structors
  548. explicit swap_with(Variant& toswap)
  549. : toswap_(toswap)
  550. {
  551. }
  552. public: // internal visitor interfaces
  553. template <typename T>
  554. void operator()(T& operand) const
  555. {
  556. // Since the precondition ensures types are same, get T...
  557. known_get<T> getter;
  558. T& other = toswap_.apply_visitor(getter);
  559. // ...and swap:
  560. ::boost::detail::variant::move_swap( operand, other );
  561. }
  562. private:
  563. swap_with& operator=(const swap_with&);
  564. };
  565. ///////////////////////////////////////////////////////////////////////////////
  566. // (detail) class reflect
  567. //
  568. // Generic static visitor that performs a typeid on the value it visits.
  569. //
  570. #if !defined(BOOST_NO_TYPEID)
  571. class reflect
  572. : public static_visitor<const std::type_info&>
  573. {
  574. public: // visitor interfaces
  575. template <typename T>
  576. const std::type_info& operator()(const T&) const
  577. {
  578. return typeid(T);
  579. }
  580. };
  581. #endif // BOOST_NO_TYPEID
  582. ///////////////////////////////////////////////////////////////////////////////
  583. // (detail) class comparer
  584. //
  585. // Generic static visitor that compares the content of the given lhs variant
  586. // with the visited rhs content using Comp.
  587. //
  588. // Precondition: lhs.which() == rhs.which()
  589. //
  590. template <typename Variant, typename Comp>
  591. class comparer
  592. : public static_visitor<bool>
  593. {
  594. private: // representation
  595. const Variant& lhs_;
  596. public: // structors
  597. explicit comparer(const Variant& lhs)
  598. : lhs_(lhs)
  599. {
  600. }
  601. public: // visitor interfaces
  602. template <typename T>
  603. bool operator()(const T& rhs_content) const
  604. {
  605. // Since the precondition ensures lhs and rhs types are same, get T...
  606. known_get<const T> getter;
  607. const T& lhs_content = lhs_.apply_visitor(getter);
  608. // ...and compare lhs and rhs contents:
  609. return Comp()(lhs_content, rhs_content);
  610. }
  611. private:
  612. comparer& operator=(const comparer&);
  613. };
  614. ///////////////////////////////////////////////////////////////////////////////
  615. // (detail) class equal_comp
  616. //
  617. // Generic function object compares lhs with rhs using operator==.
  618. //
  619. struct equal_comp
  620. {
  621. template <typename T>
  622. bool operator()(const T& lhs, const T& rhs) const
  623. {
  624. return lhs == rhs;
  625. }
  626. };
  627. ///////////////////////////////////////////////////////////////////////////////
  628. // (detail) class less_comp
  629. //
  630. // Generic function object compares lhs with rhs using operator<.
  631. //
  632. struct less_comp
  633. {
  634. template <typename T>
  635. bool operator()(const T& lhs, const T& rhs) const
  636. {
  637. return lhs < rhs;
  638. }
  639. };
  640. ///////////////////////////////////////////////////////////////////////////////
  641. // (detail) class template invoke_visitor
  642. //
  643. // Internal visitor that invokes the given visitor using:
  644. // * for wrappers (e.g., recursive_wrapper), the wrapper's held value.
  645. // * for all other values, the value itself.
  646. //
  647. template <typename Visitor>
  648. class invoke_visitor
  649. {
  650. private: // representation
  651. Visitor& visitor_;
  652. public: // visitor typedefs
  653. typedef typename Visitor::result_type
  654. result_type;
  655. public: // structors
  656. explicit invoke_visitor(Visitor& visitor)
  657. : visitor_(visitor)
  658. {
  659. }
  660. #if !defined(BOOST_NO_VOID_RETURNS)
  661. public: // internal visitor interfaces
  662. template <typename T>
  663. result_type internal_visit(T& operand, int)
  664. {
  665. return visitor_(operand);
  666. }
  667. # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
  668. template <typename T>
  669. result_type internal_visit(const T& operand, int)
  670. {
  671. return visitor_(operand);
  672. }
  673. # endif
  674. #else // defined(BOOST_NO_VOID_RETURNS)
  675. private: // helpers, for internal visitor interfaces (below)
  676. template <typename T>
  677. BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
  678. visit_impl(T& operand, mpl::false_)
  679. {
  680. return visitor_(operand);
  681. }
  682. template <typename T>
  683. BOOST_VARIANT_AUX_RETURN_VOID_TYPE
  684. visit_impl(T& operand, mpl::true_)
  685. {
  686. visitor_(operand);
  687. BOOST_VARIANT_AUX_RETURN_VOID;
  688. }
  689. public: // internal visitor interfaces
  690. template <typename T>
  691. BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
  692. internal_visit(T& operand, int)
  693. {
  694. typedef typename is_same<result_type, void>::type
  695. has_void_result_type;
  696. return visit_impl(operand, has_void_result_type());
  697. }
  698. #endif // BOOST_NO_VOID_RETURNS) workaround
  699. public: // internal visitor interfaces, cont.
  700. template <typename T>
  701. BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
  702. internal_visit(boost::recursive_wrapper<T>& operand, long)
  703. {
  704. return internal_visit( operand.get(), 1L );
  705. }
  706. template <typename T>
  707. BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
  708. internal_visit(const boost::recursive_wrapper<T>& operand, long)
  709. {
  710. return internal_visit( operand.get(), 1L );
  711. }
  712. template <typename T>
  713. BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
  714. internal_visit(boost::detail::reference_content<T>& operand, long)
  715. {
  716. return internal_visit( operand.get(), 1L );
  717. }
  718. template <typename T>
  719. BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
  720. internal_visit(const boost::detail::reference_content<T>& operand, long)
  721. {
  722. return internal_visit( operand.get(), 1L );
  723. }
  724. template <typename T>
  725. BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
  726. internal_visit(boost::detail::variant::backup_holder<T>& operand, long)
  727. {
  728. return internal_visit( operand.get(), 1L );
  729. }
  730. template <typename T>
  731. BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
  732. internal_visit(const boost::detail::variant::backup_holder<T>& operand, long)
  733. {
  734. return internal_visit( operand.get(), 1L );
  735. }
  736. #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
  737. private:
  738. // silence MSVC warning C4512: assignment operator could not be generated
  739. invoke_visitor& operator= (invoke_visitor const&);
  740. #endif
  741. };
  742. }} // namespace detail::variant
  743. ///////////////////////////////////////////////////////////////////////////////
  744. // class template variant (concept inspired by Andrei Alexandrescu)
  745. //
  746. // See docs and boost/variant/variant_fwd.hpp for more information.
  747. //
  748. template <
  749. typename T0_
  750. , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)
  751. >
  752. class variant
  753. {
  754. private: // helpers, for typedefs (below)
  755. typedef variant wknd_self_t;
  756. struct is_recursive_
  757. : detail::variant::is_recursive_flag<T0_>
  758. {
  759. };
  760. typedef typename mpl::eval_if<
  761. is_recursive_
  762. , T0_
  763. , mpl::identity< T0_ >
  764. >::type unwrapped_T0_;
  765. struct is_sequence_based_
  766. : detail::variant::is_over_sequence<unwrapped_T0_>
  767. {
  768. };
  769. #if !defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
  770. private: // helpers, for typedefs (below)
  771. typedef typename mpl::eval_if<
  772. is_sequence_based_
  773. , unwrapped_T0_ // over_sequence<...>::type
  774. , detail::variant::make_variant_list<
  775. unwrapped_T0_
  776. , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)
  777. >
  778. >::type specified_types;
  779. BOOST_STATIC_ASSERT((
  780. ::boost::mpl::not_< mpl::empty<specified_types> >::value
  781. ));
  782. typedef typename mpl::eval_if<
  783. is_recursive_
  784. , mpl::transform<
  785. specified_types
  786. , mpl::protect<
  787. detail::variant::quoted_enable_recursive<wknd_self_t>
  788. >
  789. >
  790. , mpl::identity< specified_types >
  791. >::type recursive_enabled_types;
  792. public: // public typedefs
  793. typedef typename mpl::transform<
  794. recursive_enabled_types
  795. , unwrap_recursive<mpl::_1>
  796. >::type types;
  797. private: // internal typedefs
  798. typedef typename mpl::transform<
  799. recursive_enabled_types
  800. , mpl::protect< detail::make_reference_content<> >
  801. >::type internal_types;
  802. typedef typename mpl::front<
  803. internal_types
  804. >::type internal_T0;
  805. #else // defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
  806. private: // helpers, for typedefs (below)
  807. typedef unwrapped_T0_ T0;
  808. #define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \
  809. typedef typename mpl::eval_if< \
  810. is_recursive_ \
  811. , detail::variant::enable_recursive< \
  812. BOOST_PP_CAT(T,N) \
  813. , wknd_self_t \
  814. > \
  815. , mpl::identity< BOOST_PP_CAT(T,N) > \
  816. >::type BOOST_PP_CAT(recursive_enabled_T,N); \
  817. /**/
  818. BOOST_PP_REPEAT(
  819. BOOST_VARIANT_LIMIT_TYPES
  820. , BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
  821. , _
  822. )
  823. #undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
  824. #define BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS(z,N,_) \
  825. typedef typename unwrap_recursive< \
  826. BOOST_PP_CAT(recursive_enabled_T,N) \
  827. >::type BOOST_PP_CAT(public_T,N); \
  828. /**/
  829. BOOST_PP_REPEAT(
  830. BOOST_VARIANT_LIMIT_TYPES
  831. , BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
  832. , _
  833. )
  834. #undef BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
  835. public: // public typedefs
  836. typedef typename detail::variant::make_variant_list<
  837. BOOST_VARIANT_ENUM_PARAMS(public_T)
  838. >::type types;
  839. private: // helpers, for internal typedefs (below)
  840. #define BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS(z,N,_) \
  841. typedef detail::make_reference_content< \
  842. BOOST_PP_CAT(recursive_enabled_T,N) \
  843. >::type BOOST_PP_CAT(internal_T,N); \
  844. /**/
  845. BOOST_PP_REPEAT(
  846. BOOST_VARIANT_LIMIT_TYPES
  847. , BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
  848. , _
  849. )
  850. #undef BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
  851. private: // internal typedefs
  852. typedef typename detail::variant::make_variant_list<
  853. BOOST_VARIANT_ENUM_PARAMS(internal_T)
  854. >::type internal_types;
  855. private: // static precondition assertions
  856. // NOTE TO USER :
  857. // variant< type-sequence > syntax is not supported on this compiler!
  858. //
  859. BOOST_MPL_ASSERT_NOT(( is_sequence_based_ ));
  860. #endif // BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT workaround
  861. private: // helpers, for representation (below)
  862. typedef typename detail::variant::find_fallback_type<
  863. internal_types
  864. >::type fallback_type_result_;
  865. typedef typename fallback_type_result_::first
  866. fallback_type_index_;
  867. typedef typename fallback_type_result_::second
  868. fallback_type_;
  869. struct has_fallback_type_
  870. : mpl::not_<
  871. is_same< fallback_type_, detail::variant::no_fallback_type >
  872. >
  873. {
  874. };
  875. typedef has_fallback_type_
  876. never_uses_backup_flag;
  877. typedef typename detail::variant::make_storage<
  878. internal_types, never_uses_backup_flag
  879. >::type storage_t;
  880. private: // helpers, for representation (below)
  881. // which_ on:
  882. // * [0, size<internal_types>) indicates stack content
  883. // * [-size<internal_types>, 0) indicates pointer to heap backup
  884. // if which_ >= 0:
  885. // * then which() -> which_
  886. // * else which() -> -(which_ + 1)
  887. #if !defined(BOOST_VARIANT_MINIMIZE_SIZE)
  888. typedef int which_t;
  889. #else // defined(BOOST_VARIANT_MINIMIZE_SIZE)
  890. // [if O1_size available, then attempt which_t size optimization...]
  891. // [select signed char if fewer than SCHAR_MAX types, else signed int:]
  892. typedef typename mpl::eval_if<
  893. mpl::equal_to< mpl::O1_size<internal_types>, mpl::long_<-1> >
  894. , mpl::identity< int >
  895. , mpl::if_<
  896. mpl::less< mpl::O1_size<internal_types>, mpl::int_<SCHAR_MAX> >
  897. , signed char
  898. , int
  899. >
  900. >::type which_t;
  901. #endif // BOOST_VARIANT_MINIMIZE_SIZE switch
  902. // representation -- private when possible
  903. #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
  904. private:
  905. #else
  906. public:
  907. #endif
  908. which_t which_;
  909. storage_t storage_;
  910. void indicate_which(int which)
  911. {
  912. which_ = static_cast<which_t>( which );
  913. }
  914. void indicate_backup_which(int which)
  915. {
  916. which_ = static_cast<which_t>( -(which + 1) );
  917. }
  918. private: // helpers, for queries (below)
  919. bool using_backup() const
  920. {
  921. return which_ < 0;
  922. }
  923. public: // queries
  924. int which() const
  925. {
  926. // If using heap backup...
  927. if (using_backup())
  928. // ...then return adjusted which_:
  929. return -(which_ + 1);
  930. // Otherwise, return which_ directly:
  931. return which_;
  932. }
  933. private: // helpers, for structors (below)
  934. struct initializer
  935. : BOOST_VARIANT_AUX_INITIALIZER_T(
  936. recursive_enabled_types, recursive_enabled_T
  937. )
  938. {
  939. };
  940. void destroy_content()
  941. {
  942. detail::variant::destroyer visitor;
  943. this->internal_apply_visitor(visitor);
  944. }
  945. public: // structors
  946. ~variant()
  947. {
  948. destroy_content();
  949. }
  950. variant()
  951. {
  952. // NOTE TO USER :
  953. // Compile error from here indicates that the first bound
  954. // type is not default-constructible, and so variant cannot
  955. // support its own default-construction.
  956. //
  957. new( storage_.address() ) internal_T0();
  958. indicate_which(0); // zero is the index of the first bounded type
  959. }
  960. private: // helpers, for structors, cont. (below)
  961. class convert_copy_into
  962. : public static_visitor<int>
  963. {
  964. private: // representation
  965. void* storage_;
  966. public: // structors
  967. explicit convert_copy_into(void* storage)
  968. : storage_(storage)
  969. {
  970. }
  971. public: // internal visitor interfaces (below)
  972. template <typename T>
  973. int internal_visit(T& operand, int) const
  974. {
  975. // NOTE TO USER :
  976. // Compile error here indicates one of the source variant's types
  977. // cannot be unambiguously converted to the destination variant's
  978. // types (or that no conversion exists).
  979. //
  980. return initializer::initialize(storage_, operand);
  981. }
  982. # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
  983. template <typename T>
  984. result_type internal_visit(const T& operand, int) const
  985. {
  986. return initializer::initialize(storage_, operand);
  987. }
  988. # endif
  989. template <typename T>
  990. int internal_visit(boost::detail::reference_content<T>& operand, long) const
  991. {
  992. return internal_visit( operand.get(), 1L );
  993. }
  994. template <typename T>
  995. int internal_visit(const boost::detail::reference_content<T>& operand, long) const
  996. {
  997. return internal_visit( operand.get(), 1L );
  998. }
  999. template <typename T>
  1000. int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
  1001. {
  1002. return internal_visit( operand.get(), 1L );
  1003. }
  1004. template <typename T>
  1005. int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
  1006. {
  1007. return internal_visit( operand.get(), 1L );
  1008. }
  1009. template <typename T>
  1010. int internal_visit(boost::recursive_wrapper<T>& operand, long) const
  1011. {
  1012. return internal_visit( operand.get(), 1L );
  1013. }
  1014. template <typename T>
  1015. int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
  1016. {
  1017. return internal_visit( operand.get(), 1L );
  1018. }
  1019. };
  1020. friend class convert_copy_into;
  1021. private: // helpers, for structors, below
  1022. template <typename T>
  1023. void convert_construct(
  1024. T& operand
  1025. , int
  1026. , mpl::false_ = mpl::false_() // is_foreign_variant
  1027. )
  1028. {
  1029. // NOTE TO USER :
  1030. // Compile error here indicates that the given type is not
  1031. // unambiguously convertible to one of the variant's types
  1032. // (or that no conversion exists).
  1033. //
  1034. indicate_which(
  1035. initializer::initialize(
  1036. storage_.address()
  1037. , operand
  1038. )
  1039. );
  1040. }
  1041. template <typename Variant>
  1042. void convert_construct(
  1043. Variant& operand
  1044. , long
  1045. , mpl::true_// is_foreign_variant
  1046. )
  1047. {
  1048. convert_copy_into visitor(storage_.address());
  1049. indicate_which(
  1050. operand.internal_apply_visitor(visitor)
  1051. );
  1052. }
  1053. template <typename Variant>
  1054. void convert_construct_variant(Variant& operand)
  1055. {
  1056. // [Determine if the given variant is itself a bounded type, or if its
  1057. // content needs to be converted (i.e., it is a 'foreign' variant):]
  1058. //
  1059. typedef typename mpl::find_if<
  1060. types
  1061. , is_same<
  1062. add_const<mpl::_1>
  1063. , const Variant
  1064. >
  1065. >::type found_it;
  1066. typedef typename mpl::end<types>::type not_found;
  1067. typedef typename is_same<
  1068. found_it, not_found
  1069. >::type is_foreign_variant;
  1070. // Convert construct from operand:
  1071. convert_construct(
  1072. operand, 1L
  1073. , is_foreign_variant()
  1074. );
  1075. }
  1076. template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
  1077. void convert_construct(
  1078. boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
  1079. , long
  1080. )
  1081. {
  1082. convert_construct_variant(operand);
  1083. }
  1084. template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
  1085. void convert_construct(
  1086. const boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
  1087. , long
  1088. )
  1089. {
  1090. convert_construct_variant(operand);
  1091. }
  1092. public: // structors, cont.
  1093. #if !defined(BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING)
  1094. template <typename T>
  1095. variant(const T& operand)
  1096. {
  1097. convert_construct(operand, 1L);
  1098. }
  1099. template <typename T>
  1100. variant(T& operand)
  1101. {
  1102. convert_construct(operand, 1L);
  1103. }
  1104. #elif defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND)
  1105. // For compilers that cannot distinguish between T& and const T& in
  1106. // template constructors, but do fully support SFINAE, we can workaround:
  1107. template <typename T>
  1108. variant(const T& operand)
  1109. {
  1110. convert_construct(operand, 1L);
  1111. }
  1112. template <typename T>
  1113. variant(
  1114. T& operand
  1115. , typename enable_if<
  1116. mpl::not_< is_const<T> >
  1117. , void
  1118. >::type* = 0
  1119. )
  1120. {
  1121. convert_construct(operand, 1L);
  1122. }
  1123. #else // !defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND)
  1124. // For compilers that cannot distinguish between T& and const T& in
  1125. // template constructors, and do NOT support SFINAE, we can't workaround:
  1126. template <typename T>
  1127. variant(const T& operand)
  1128. {
  1129. convert_construct(operand, 1L);
  1130. }
  1131. #endif // BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING workarounds
  1132. public: // structors, cont.
  1133. // [MSVC6 requires copy constructor appear after template constructors]
  1134. variant(const variant& operand)
  1135. {
  1136. // Copy the value of operand into *this...
  1137. detail::variant::copy_into visitor( storage_.address() );
  1138. operand.internal_apply_visitor(visitor);
  1139. // ...and activate the *this's primary storage on success:
  1140. indicate_which(operand.which());
  1141. }
  1142. private: // helpers, for modifiers (below)
  1143. # if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
  1144. template <typename Variant, typename RhsT>
  1145. friend class detail::variant::backup_assigner;
  1146. # endif
  1147. // class assigner
  1148. //
  1149. // Internal visitor that "assigns" the visited value to the given variant
  1150. // by appropriate destruction and copy-construction.
  1151. //
  1152. class assigner
  1153. : public static_visitor<>
  1154. {
  1155. private: // representation
  1156. variant& lhs_;
  1157. int rhs_which_;
  1158. public: // structors
  1159. assigner(variant& lhs, int rhs_which)
  1160. : lhs_(lhs)
  1161. , rhs_which_(rhs_which)
  1162. {
  1163. }
  1164. private: // helpers, for internal visitor interface (below)
  1165. template <typename RhsT, typename B1, typename B2>
  1166. void assign_impl(
  1167. const RhsT& rhs_content
  1168. , mpl::true_// has_nothrow_copy
  1169. , B1// has_nothrow_move_constructor
  1170. , B2// has_fallback_type
  1171. )
  1172. {
  1173. // Destroy lhs's content...
  1174. lhs_.destroy_content(); // nothrow
  1175. // ...copy rhs content into lhs's storage...
  1176. new(lhs_.storage_.address())
  1177. RhsT( rhs_content ); // nothrow
  1178. // ...and indicate new content type:
  1179. lhs_.indicate_which(rhs_which_); // nothrow
  1180. }
  1181. template <typename RhsT, typename B>
  1182. void assign_impl(
  1183. const RhsT& rhs_content
  1184. , mpl::false_// has_nothrow_copy
  1185. , mpl::true_// has_nothrow_move_constructor
  1186. , B// has_fallback_type
  1187. )
  1188. {
  1189. // Attempt to make a temporary copy (so as to move it below)...
  1190. RhsT temp(rhs_content);
  1191. // ...and upon success destroy lhs's content...
  1192. lhs_.destroy_content(); // nothrow
  1193. // ...move the temporary copy into lhs's storage...
  1194. new(lhs_.storage_.address())
  1195. RhsT( detail::variant::move(temp) ); // nothrow
  1196. // ...and indicate new content type:
  1197. lhs_.indicate_which(rhs_which_); // nothrow
  1198. }
  1199. template <typename RhsT>
  1200. void assign_impl(
  1201. const RhsT& rhs_content
  1202. , mpl::false_// has_nothrow_copy
  1203. , mpl::false_// has_nothrow_move_constructor
  1204. , mpl::true_// has_fallback_type
  1205. )
  1206. {
  1207. // Destroy lhs's content...
  1208. lhs_.destroy_content(); // nothrow
  1209. try
  1210. {
  1211. // ...and attempt to copy rhs's content into lhs's storage:
  1212. new(lhs_.storage_.address())
  1213. RhsT( rhs_content );
  1214. }
  1215. catch (...)
  1216. {
  1217. // In case of failure, default-construct fallback type in lhs's storage...
  1218. new (lhs_.storage_.address())
  1219. fallback_type_; // nothrow
  1220. // ...indicate construction of fallback type...
  1221. lhs_.indicate_which(
  1222. BOOST_MPL_AUX_VALUE_WKND(fallback_type_index_)::value
  1223. ); // nothrow
  1224. // ...and rethrow:
  1225. throw;
  1226. }
  1227. // In the event of success, indicate new content type:
  1228. lhs_.indicate_which(rhs_which_); // nothrow
  1229. }
  1230. template <typename RhsT>
  1231. void assign_impl(
  1232. const RhsT& rhs_content
  1233. , mpl::false_// has_nothrow_copy
  1234. , mpl::false_// has_nothrow_move_constructor
  1235. , mpl::false_// has_fallback_type
  1236. )
  1237. {
  1238. detail::variant::backup_assigner<wknd_self_t, RhsT>
  1239. visitor(lhs_, rhs_which_, rhs_content);
  1240. lhs_.internal_apply_visitor(visitor);
  1241. }
  1242. public: // internal visitor interfaces
  1243. template <typename RhsT>
  1244. BOOST_VARIANT_AUX_RETURN_VOID_TYPE
  1245. internal_visit(const RhsT& rhs_content, int)
  1246. {
  1247. typedef typename has_nothrow_copy<RhsT>::type
  1248. nothrow_copy;
  1249. typedef typename mpl::or_< // reduces compile-time
  1250. nothrow_copy
  1251. , detail::variant::has_nothrow_move_constructor<RhsT>
  1252. >::type nothrow_move_constructor;
  1253. assign_impl(
  1254. rhs_content
  1255. , nothrow_copy()
  1256. , nothrow_move_constructor()
  1257. , has_fallback_type_()
  1258. );
  1259. BOOST_VARIANT_AUX_RETURN_VOID;
  1260. }
  1261. #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
  1262. private:
  1263. // silence MSVC warning C4512: assignment operator could not be generated
  1264. assigner& operator= (assigner const&);
  1265. #endif
  1266. };
  1267. friend class assigner;
  1268. void variant_assign(const variant& rhs)
  1269. {
  1270. // If the contained types are EXACTLY the same...
  1271. if (which_ == rhs.which_)
  1272. {
  1273. // ...then assign rhs's storage to lhs's content:
  1274. detail::variant::assign_storage visitor(rhs.storage_.address());
  1275. this->internal_apply_visitor(visitor);
  1276. }
  1277. else
  1278. {
  1279. // Otherwise, perform general (copy-based) variant assignment:
  1280. assigner visitor(*this, rhs.which());
  1281. rhs.internal_apply_visitor(visitor);
  1282. }
  1283. }
  1284. private: // helpers, for modifiers (below)
  1285. template <typename T>
  1286. void assign(const T& rhs)
  1287. {
  1288. // If direct T-to-T assignment is not possible...
  1289. detail::variant::direct_assigner<T> direct_assign(rhs);
  1290. if (this->apply_visitor(direct_assign) == false)
  1291. {
  1292. // ...then convert rhs to variant and assign:
  1293. //
  1294. // While potentially inefficient, the following construction of a
  1295. // variant allows T as any type convertible to one of the bounded
  1296. // types without excessive code redundancy.
  1297. //
  1298. variant temp(rhs);
  1299. variant_assign( detail::variant::move(temp) );
  1300. }
  1301. }
  1302. public: // modifiers
  1303. template <typename T>
  1304. variant& operator=(const T& rhs)
  1305. {
  1306. assign(rhs);
  1307. return *this;
  1308. }
  1309. // [MSVC6 requires copy assign appear after templated operator=]
  1310. variant& operator=(const variant& rhs)
  1311. {
  1312. variant_assign(rhs);
  1313. return *this;
  1314. }
  1315. void swap(variant& rhs)
  1316. {
  1317. // If the contained types are the same...
  1318. if (which() == rhs.which())
  1319. {
  1320. // ...then swap the values directly:
  1321. detail::variant::swap_with<variant> visitor(rhs);
  1322. this->apply_visitor(visitor);
  1323. }
  1324. else
  1325. {
  1326. // ...otherwise, perform general variant swap:
  1327. variant tmp( detail::variant::move(rhs) );
  1328. rhs = detail::variant::move(*this);
  1329. *this = detail::variant::move(tmp);
  1330. }
  1331. }
  1332. public: // queries
  1333. //
  1334. // NOTE: member which() defined above.
  1335. //
  1336. bool empty() const
  1337. {
  1338. return false;
  1339. }
  1340. #if !defined(BOOST_NO_TYPEID)
  1341. const std::type_info& type() const
  1342. {
  1343. detail::variant::reflect visitor;
  1344. return this->apply_visitor(visitor);
  1345. }
  1346. #endif
  1347. public: // prevent comparison with foreign types
  1348. #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
  1349. # define BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE \
  1350. void
  1351. #else // MSVC7
  1352. //
  1353. // MSVC7 gives error about return types for above being different than
  1354. // the true comparison operator overloads:
  1355. //
  1356. # define BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE \
  1357. bool
  1358. #endif // MSVC7 workaround
  1359. template <typename U>
  1360. BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE
  1361. operator==(const U&) const
  1362. {
  1363. BOOST_STATIC_ASSERT( false && sizeof(U) );
  1364. }
  1365. template <typename U>
  1366. BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE
  1367. operator<(const U&) const
  1368. {
  1369. BOOST_STATIC_ASSERT( false && sizeof(U) );
  1370. }
  1371. public: // comparison operators
  1372. // [MSVC6 requires these operators appear after template operators]
  1373. bool operator==(const variant& rhs) const
  1374. {
  1375. if (this->which() != rhs.which())
  1376. return false;
  1377. detail::variant::comparer<
  1378. variant, detail::variant::equal_comp
  1379. > visitor(*this);
  1380. return rhs.apply_visitor(visitor);
  1381. }
  1382. bool operator<(const variant& rhs) const
  1383. {
  1384. //
  1385. // Dirk Schreib suggested this collating order.
  1386. //
  1387. if (this->which() != rhs.which())
  1388. return this->which() < rhs.which();
  1389. detail::variant::comparer<
  1390. variant, detail::variant::less_comp
  1391. > visitor(*this);
  1392. return rhs.apply_visitor(visitor);
  1393. }
  1394. // helpers, for visitation support (below) -- private when possible
  1395. #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
  1396. template < BOOST_VARIANT_ENUM_PARAMS(typename U) >
  1397. friend class variant;
  1398. private:
  1399. #else// defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
  1400. public:
  1401. #endif// !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
  1402. template <typename Visitor, typename VoidPtrCV>
  1403. static
  1404. BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
  1405. typename Visitor::result_type
  1406. )
  1407. internal_apply_visitor_impl(
  1408. int internal_which
  1409. , int logical_which
  1410. , Visitor& visitor
  1411. , VoidPtrCV storage
  1412. )
  1413. {
  1414. typedef mpl::int_<0> first_which;
  1415. typedef typename mpl::begin<internal_types>::type first_it;
  1416. typedef typename mpl::end<internal_types>::type last_it;
  1417. typedef detail::variant::visitation_impl_step<
  1418. first_it, last_it
  1419. > first_step;
  1420. return detail::variant::visitation_impl(
  1421. internal_which, logical_which
  1422. , visitor, storage, mpl::false_()
  1423. , never_uses_backup_flag()
  1424. , static_cast<first_which*>(0), static_cast<first_step*>(0)
  1425. );
  1426. }
  1427. template <typename Visitor>
  1428. BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
  1429. typename Visitor::result_type
  1430. )
  1431. internal_apply_visitor(Visitor& visitor)
  1432. {
  1433. return internal_apply_visitor_impl(
  1434. which_, which(), visitor, storage_.address()
  1435. );
  1436. }
  1437. template <typename Visitor>
  1438. BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
  1439. typename Visitor::result_type
  1440. )
  1441. internal_apply_visitor(Visitor& visitor) const
  1442. {
  1443. return internal_apply_visitor_impl(
  1444. which_, which(), visitor, storage_.address()
  1445. );
  1446. }
  1447. public: // visitation support
  1448. template <typename Visitor>
  1449. BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
  1450. typename Visitor::result_type
  1451. )
  1452. apply_visitor(Visitor& visitor)
  1453. {
  1454. detail::variant::invoke_visitor<Visitor> invoker(visitor);
  1455. return this->internal_apply_visitor(invoker);
  1456. }
  1457. template <typename Visitor>
  1458. BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
  1459. typename Visitor::result_type
  1460. )
  1461. apply_visitor(Visitor& visitor) const
  1462. {
  1463. detail::variant::invoke_visitor<Visitor> invoker(visitor);
  1464. return this->internal_apply_visitor(invoker);
  1465. }
  1466. }; // class variant
  1467. ///////////////////////////////////////////////////////////////////////////////
  1468. // metafunction make_variant_over
  1469. //
  1470. // See docs and boost/variant/variant_fwd.hpp for more information.
  1471. //
  1472. template <typename Types>
  1473. struct make_variant_over
  1474. {
  1475. private: // precondition assertions
  1476. #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
  1477. BOOST_STATIC_ASSERT(( ::boost::mpl::is_sequence<Types>::value ));
  1478. #endif
  1479. public: // metafunction result
  1480. typedef variant<
  1481. detail::variant::over_sequence< Types >
  1482. > type;
  1483. };
  1484. ///////////////////////////////////////////////////////////////////////////////
  1485. // function template swap
  1486. //
  1487. // Swaps two variants of the same type (i.e., identical specification).
  1488. //
  1489. template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
  1490. inline void swap(
  1491. variant< BOOST_VARIANT_ENUM_PARAMS(T) >& lhs
  1492. , variant< BOOST_VARIANT_ENUM_PARAMS(T) >& rhs
  1493. )
  1494. {
  1495. lhs.swap(rhs);
  1496. }
  1497. } // namespace boost
  1498. // implementation additions
  1499. #if !defined(BOOST_NO_IOSTREAM)
  1500. #include "boost/variant/detail/variant_io.hpp"
  1501. #endif // BOOST_NO_IOSTREAM
  1502. #endif // BOOST_VARIANT_VARIANT_HPP