env.hpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // env.hpp
  3. // Helpers for producing and consuming tranform env variables.
  4. //
  5. // Copyright 2012 Eric Niebler. Distributed under the Boost
  6. // Software License, Version 1.0. (See accompanying file
  7. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  8. #ifndef BOOST_PROTO_TRANSFORM_ENV_HPP_EAN_18_07_2012
  9. #define BOOST_PROTO_TRANSFORM_ENV_HPP_EAN_18_07_2012
  10. #include <boost/config.hpp>
  11. #include <boost/detail/workaround.hpp>
  12. #include <boost/ref.hpp>
  13. #include <boost/utility/enable_if.hpp>
  14. #include <boost/type_traits/is_const.hpp>
  15. #include <boost/type_traits/is_same.hpp>
  16. #include <boost/type_traits/add_const.hpp>
  17. #include <boost/type_traits/add_reference.hpp>
  18. #include <boost/type_traits/remove_const.hpp>
  19. #include <boost/mpl/assert.hpp>
  20. #include <boost/mpl/bool.hpp>
  21. #include <boost/mpl/if.hpp>
  22. #include <boost/mpl/not.hpp>
  23. #include <boost/proto/proto_fwd.hpp>
  24. #include <boost/proto/transform/impl.hpp>
  25. #include <boost/proto/detail/poly_function.hpp>
  26. #include <boost/proto/detail/is_noncopyable.hpp>
  27. #ifdef _MSC_VER
  28. # pragma warning(push)
  29. # pragma warning(disable: 4180) // qualifier applied to function type has no meaning; ignored
  30. #endif
  31. namespace boost
  32. {
  33. namespace proto
  34. {
  35. namespace detail
  36. {
  37. template<typename T>
  38. struct value_type
  39. {
  40. typedef typename remove_const<T>::type value;
  41. typedef typename add_reference<T>::type reference;
  42. typedef typename mpl::if_c<is_noncopyable<T>::value, reference, value>::type type;
  43. };
  44. template<typename T>
  45. struct value_type<T &>
  46. {
  47. typedef T &value;
  48. typedef T &reference;
  49. typedef T &type;
  50. };
  51. }
  52. #define BOOST_PROTO_DEFINE_ENV_VAR(TAG, NAME) \
  53. struct TAG \
  54. { \
  55. template<typename Value> \
  56. boost::proto::env<TAG, Value &> const \
  57. operator =(boost::reference_wrapper<Value> &value) const \
  58. { \
  59. return boost::proto::env<TAG, Value &>(value.get()); \
  60. } \
  61. template<typename Value> \
  62. boost::proto::env<TAG, Value &> const \
  63. operator =(boost::reference_wrapper<Value> const &value) const \
  64. { \
  65. return boost::proto::env<TAG, Value &>(value.get()); \
  66. } \
  67. template<typename Value> \
  68. typename boost::disable_if_c< \
  69. boost::is_const<Value>::value \
  70. , boost::proto::env<TAG, typename boost::proto::detail::value_type<Value>::type> \
  71. >::type const operator =(Value &value) const \
  72. { \
  73. return boost::proto::env<TAG, typename boost::proto::detail::value_type<Value>::type>(value); \
  74. } \
  75. template<typename Value> \
  76. boost::proto::env<TAG, typename boost::proto::detail::value_type<Value const>::type> const \
  77. operator =(Value const &value) const \
  78. { \
  79. return boost::proto::env<TAG, typename boost::proto::detail::value_type<Value const>::type>(value); \
  80. } \
  81. }; \
  82. \
  83. TAG const NAME = {} \
  84. /**/
  85. namespace envns_
  86. {
  87. ////////////////////////////////////////////////////////////////////////////////////////////
  88. // env
  89. // A transform env is a slot-based storage mechanism, accessible by tag.
  90. template<typename Key, typename Value, typename Base /*= empty_env*/>
  91. struct env
  92. : private Base
  93. {
  94. private:
  95. Value value_;
  96. public:
  97. typedef Value value_type;
  98. typedef typename add_reference<Value>::type reference;
  99. typedef typename add_reference<typename add_const<Value>::type>::type const_reference;
  100. typedef void proto_environment_; ///< INTERNAL ONLY
  101. explicit env(const_reference value, Base const &base = Base())
  102. : Base(base)
  103. , value_(value)
  104. {}
  105. #if BOOST_WORKAROUND(__GNUC__, == 3) || (BOOST_WORKAROUND(__GNUC__, == 4) && __GNUC_MINOR__ <= 2)
  106. /// INTERNAL ONLY
  107. struct found
  108. {
  109. typedef Value type;
  110. typedef typename add_reference<typename add_const<Value>::type>::type const_reference;
  111. };
  112. template<typename OtherKey, typename OtherValue = key_not_found>
  113. struct lookup
  114. : mpl::if_c<
  115. is_same<OtherKey, Key>::value
  116. , found
  117. , typename Base::template lookup<OtherKey, OtherValue>
  118. >::type
  119. {};
  120. #else
  121. /// INTERNAL ONLY
  122. template<typename OtherKey, typename OtherValue = key_not_found>
  123. struct lookup
  124. : Base::template lookup<OtherKey, OtherValue>
  125. {};
  126. /// INTERNAL ONLY
  127. template<typename OtherValue>
  128. struct lookup<Key, OtherValue>
  129. {
  130. typedef Value type;
  131. typedef typename add_reference<typename add_const<Value>::type>::type const_reference;
  132. };
  133. #endif
  134. // For key-based lookups not intended to fail
  135. using Base::operator[];
  136. const_reference operator[](Key) const
  137. {
  138. return this->value_;
  139. }
  140. // For key-based lookups that can fail, use the default if key not found.
  141. using Base::at;
  142. template<typename T>
  143. const_reference at(Key, T const &) const
  144. {
  145. return this->value_;
  146. }
  147. };
  148. // define proto::data_type type and proto::data global
  149. BOOST_PROTO_DEFINE_ENV_VAR(data_type, data);
  150. }
  151. using envns_::data;
  152. namespace functional
  153. {
  154. ////////////////////////////////////////////////////////////////////////////////////////
  155. // as_env
  156. struct as_env
  157. {
  158. BOOST_PROTO_CALLABLE()
  159. BOOST_PROTO_POLY_FUNCTION()
  160. /// INTERNAL ONLY
  161. template<typename T, bool B = is_env<T>::value>
  162. struct impl
  163. {
  164. typedef env<data_type, typename detail::value_type<T>::type> result_type;
  165. result_type const operator()(detail::arg<T> t) const
  166. {
  167. return result_type(t());
  168. }
  169. };
  170. /// INTERNAL ONLY
  171. template<typename T>
  172. struct impl<T, true>
  173. {
  174. typedef T result_type;
  175. typename add_const<T>::type operator()(detail::arg<T> t) const
  176. {
  177. return t();
  178. }
  179. };
  180. template<typename Sig>
  181. struct result;
  182. template<typename This, typename T>
  183. struct result<This(T)>
  184. {
  185. typedef typename impl<typename detail::normalize_arg<T>::type>::result_type type;
  186. };
  187. template<typename T>
  188. typename impl<typename detail::normalize_arg<T &>::type>::result_type const
  189. operator()(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T)) const
  190. {
  191. return impl<typename detail::normalize_arg<T &>::type>()(
  192. static_cast<typename detail::normalize_arg<T &>::reference>(t)
  193. );
  194. }
  195. template<typename T>
  196. typename impl<typename detail::normalize_arg<T const &>::type>::result_type const
  197. operator()(T const &t) const
  198. {
  199. return impl<typename detail::normalize_arg<T const &>::type>()(
  200. static_cast<typename detail::normalize_arg<T const &>::reference>(t)
  201. );
  202. }
  203. };
  204. ////////////////////////////////////////////////////////////////////////////////////////
  205. // has_env_var
  206. template<typename Key>
  207. struct has_env_var
  208. : detail::poly_function<has_env_var<Key> >
  209. {
  210. BOOST_PROTO_CALLABLE()
  211. template<typename Env, bool IsEnv = is_env<Env>::value>
  212. struct impl
  213. {
  214. typedef
  215. mpl::not_<
  216. is_same<
  217. typename remove_reference<Env>::type::template lookup<Key>::type
  218. , key_not_found
  219. >
  220. >
  221. result_type;
  222. result_type operator()(detail::arg<Env>) const
  223. {
  224. return result_type();
  225. }
  226. };
  227. template<typename Env>
  228. struct impl<Env, false>
  229. {
  230. typedef mpl::false_ result_type;
  231. result_type operator()(detail::arg<Env>) const
  232. {
  233. return result_type();
  234. }
  235. };
  236. };
  237. template<>
  238. struct has_env_var<data_type>
  239. : detail::poly_function<has_env_var<data_type> >
  240. {
  241. BOOST_PROTO_CALLABLE()
  242. template<typename Env, bool IsEnv = is_env<Env>::value>
  243. struct impl
  244. {
  245. typedef
  246. mpl::not_<
  247. is_same<
  248. typename remove_reference<Env>::type::template lookup<data_type>::type
  249. , key_not_found
  250. >
  251. >
  252. result_type;
  253. result_type operator()(detail::arg<Env>) const
  254. {
  255. return result_type();
  256. }
  257. };
  258. template<typename Env>
  259. struct impl<Env, false>
  260. {
  261. typedef mpl::true_ result_type;
  262. result_type operator()(detail::arg<Env>) const
  263. {
  264. return result_type();
  265. }
  266. };
  267. };
  268. ////////////////////////////////////////////////////////////////////////////////////////
  269. // env_var
  270. template<typename Key>
  271. struct env_var
  272. : detail::poly_function<env_var<Key> >
  273. {
  274. BOOST_PROTO_CALLABLE()
  275. template<typename Env>
  276. struct impl
  277. {
  278. typedef
  279. typename remove_reference<Env>::type::template lookup<Key>::type
  280. result_type;
  281. result_type operator()(detail::arg<Env> e) const
  282. {
  283. return e()[Key()];
  284. }
  285. };
  286. };
  287. template<>
  288. struct env_var<data_type>
  289. : detail::poly_function<env_var<data_type> >
  290. {
  291. BOOST_PROTO_CALLABLE()
  292. template<typename Env, bool B = is_env<Env>::value>
  293. struct impl
  294. {
  295. typedef Env result_type;
  296. result_type operator()(detail::arg<Env> e) const
  297. {
  298. return e();
  299. }
  300. };
  301. template<typename Env>
  302. struct impl<Env, true>
  303. {
  304. typedef
  305. typename remove_reference<Env>::type::template lookup<data_type>::type
  306. result_type;
  307. result_type operator()(detail::arg<Env> e) const
  308. {
  309. return e()[proto::data];
  310. }
  311. };
  312. };
  313. }
  314. namespace result_of
  315. {
  316. template<typename T>
  317. struct as_env
  318. : BOOST_PROTO_RESULT_OF<functional::as_env(T)>
  319. {};
  320. template<typename Env, typename Key>
  321. struct has_env_var
  322. : BOOST_PROTO_RESULT_OF<functional::has_env_var<Key>(Env)>::type
  323. {};
  324. template<typename Env, typename Key>
  325. struct env_var
  326. : BOOST_PROTO_RESULT_OF<functional::env_var<Key>(Env)>
  327. {};
  328. }
  329. ////////////////////////////////////////////////////////////////////////////////////////////
  330. // as_env
  331. template<typename T>
  332. typename proto::result_of::as_env<T &>::type const as_env(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T))
  333. {
  334. return proto::functional::as_env()(t);
  335. }
  336. template<typename T>
  337. typename proto::result_of::as_env<T const &>::type const as_env(T const &t)
  338. {
  339. return proto::functional::as_env()(t);
  340. }
  341. ////////////////////////////////////////////////////////////////////////////////////////////
  342. // has_env_var
  343. template<typename Key, typename Env>
  344. typename proto::result_of::has_env_var<Env &, Key>::type has_env_var(Env &e BOOST_PROTO_DISABLE_IF_IS_CONST(Env))
  345. {
  346. return functional::has_env_var<Key>()(e);
  347. }
  348. template<typename Key, typename Env>
  349. typename proto::result_of::has_env_var<Env const &, Key>::type has_env_var(Env const &e)
  350. {
  351. return functional::has_env_var<Key>()(e);
  352. }
  353. ////////////////////////////////////////////////////////////////////////////////////////////
  354. // env_var
  355. template<typename Key, typename Env>
  356. typename proto::result_of::env_var<Env &, Key>::type env_var(Env &e BOOST_PROTO_DISABLE_IF_IS_CONST(Env))
  357. {
  358. return functional::env_var<Key>()(e);
  359. }
  360. template<typename Key, typename Env>
  361. typename proto::result_of::env_var<Env const &, Key>::type env_var(Env const &e)
  362. {
  363. return functional::env_var<Key>()(e);
  364. }
  365. namespace envns_
  366. {
  367. ////////////////////////////////////////////////////////////////////////////////////////
  368. // env operator,
  369. template<typename T, typename T1, typename V1>
  370. inline typename disable_if_c<
  371. is_const<T>::value
  372. , env<T1, V1, BOOST_PROTO_UNCVREF(typename result_of::as_env<T &>::type)>
  373. >::type const operator,(T &t, env<T1, V1> const &head)
  374. {
  375. return env<T1, V1, BOOST_PROTO_UNCVREF(typename result_of::as_env<T &>::type)>(
  376. head[T1()]
  377. , proto::as_env(t)
  378. );
  379. }
  380. template<typename T, typename T1, typename V1>
  381. inline env<T1, V1, BOOST_PROTO_UNCVREF(typename result_of::as_env<T const &>::type)> const
  382. operator,(T const &t, env<T1, V1> const &head)
  383. {
  384. return env<T1, V1, BOOST_PROTO_UNCVREF(typename result_of::as_env<T const &>::type)>(
  385. head[T1()]
  386. , proto::as_env(t)
  387. );
  388. }
  389. }
  390. ////////////////////////////////////////////////////////////////////////////////////////////
  391. // _env_var
  392. template<typename Key>
  393. struct _env_var
  394. : proto::transform<_env_var<Key> >
  395. {
  396. template<typename Expr, typename State, typename Data>
  397. struct impl
  398. : transform_impl<Expr, State, Data>
  399. {
  400. typedef typename impl::data::template lookup<Key>::type result_type;
  401. BOOST_MPL_ASSERT_NOT((is_same<result_type, key_not_found>)); // lookup failed
  402. BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::data::template lookup<Key>::const_reference)
  403. operator ()(
  404. typename impl::expr_param
  405. , typename impl::state_param
  406. , typename impl::data_param d
  407. ) const
  408. {
  409. return d[Key()];
  410. }
  411. };
  412. };
  413. struct _env
  414. : transform<_env>
  415. {
  416. template<typename Expr, typename State, typename Data>
  417. struct impl
  418. : transform_impl<Expr, State, Data>
  419. {
  420. typedef Data result_type;
  421. BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::data_param)
  422. operator ()(
  423. typename impl::expr_param
  424. , typename impl::state_param
  425. , typename impl::data_param d
  426. ) const
  427. {
  428. return d;
  429. }
  430. };
  431. };
  432. /// INTERNAL ONLY
  433. template<typename Key>
  434. struct is_callable<_env_var<Key> >
  435. : mpl::true_
  436. {};
  437. /// INTERNAL ONLY
  438. template<typename Key>
  439. struct is_callable<functional::has_env_var<Key> >
  440. : mpl::true_
  441. {};
  442. /// INTERNAL ONLY
  443. template<typename Key>
  444. struct is_callable<functional::env_var<Key> >
  445. : mpl::true_
  446. {};
  447. }
  448. }
  449. #ifdef _MSC_VER
  450. # pragma warning(pop)
  451. #endif
  452. #endif