PageRenderTime 122ms CodeModel.GetById 36ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/variant/variant.hpp

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