message.hpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. //
  2. // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See
  5. // accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. #ifndef BOOST_LOCALE_MESSAGE_HPP_INCLUDED
  9. #define BOOST_LOCALE_MESSAGE_HPP_INCLUDED
  10. #include <boost/locale/config.hpp>
  11. #ifdef BOOST_MSVC
  12. # pragma warning(push)
  13. # pragma warning(disable : 4275 4251 4231 4660)
  14. #endif
  15. #include <locale>
  16. #include <string>
  17. #include <vector>
  18. #include <set>
  19. #include <memory>
  20. #include <boost/locale/formatting.hpp>
  21. // glibc < 2.3.4 declares those as macros if compiled with optimization turned on
  22. #ifdef gettext
  23. # undef gettext
  24. # undef ngettext
  25. # undef dgettext
  26. # undef dngettext
  27. #endif
  28. namespace boost {
  29. namespace locale {
  30. ///
  31. /// \defgroup message Message Formatting (translation)
  32. ///
  33. ///This module provides message translation functionality, i.e. allow your application to speak native language
  34. ///
  35. /// @{
  36. ///
  37. /// \cond INTERNAL
  38. template<typename CharType>
  39. struct base_message_format: public std::locale::facet
  40. {
  41. };
  42. /// \endcond
  43. ///
  44. /// \brief This facet provides message formatting abilities
  45. ///
  46. template<typename CharType>
  47. class message_format : public base_message_format<CharType>
  48. {
  49. public:
  50. ///
  51. /// Character type
  52. ///
  53. typedef CharType char_type;
  54. ///
  55. /// String type
  56. ///
  57. typedef std::basic_string<CharType> string_type;
  58. ///
  59. /// Default constructor
  60. ///
  61. message_format(size_t refs = 0) :
  62. base_message_format<CharType>(refs)
  63. {
  64. }
  65. ///
  66. /// This function returns a pointer to the string for a message defined by a \a context
  67. /// and identification string \a id. Both create a single key for message lookup in
  68. /// a domain defined by \a domain_id.
  69. ///
  70. /// If \a context is NULL it is not considered to be a part of the key
  71. ///
  72. /// If a translated string is found, it is returned, otherwise NULL is returned
  73. ///
  74. ///
  75. virtual char_type const *get(int domain_id,char_type const *context,char_type const *id) const = 0;
  76. ///
  77. /// This function returns a pointer to the string for a plural message defined by a \a context
  78. /// and identification string \a single_id.
  79. ///
  80. /// If \a context is NULL it is not considered to be a part of the key
  81. ///
  82. /// Both create a single key for message lookup in
  83. /// a domain defined \a domain_id. \a n is used to pick the correct translation string for a specific
  84. /// number.
  85. ///
  86. /// If a translated string is found, it is returned, otherwise NULL is returned
  87. ///
  88. ///
  89. virtual char_type const *get(int domain_id,char_type const *context,char_type const *single_id,int n) const = 0;
  90. ///
  91. /// Convert a string that defines \a domain to the integer id used by \a get functions
  92. ///
  93. virtual int domain(std::string const &domain) const = 0;
  94. ///
  95. /// Convert the string \a msg to target locale's encoding. If \a msg is already
  96. /// in target encoding it would be returned otherwise the converted
  97. /// string is stored in temporary \a buffer and buffer.c_str() is returned.
  98. ///
  99. /// Note: for char_type that is char16_t, char32_t and wchar_t it is no-op, returns
  100. /// msg
  101. ///
  102. virtual char_type const *convert(char_type const *msg,string_type &buffer) const = 0;
  103. #if defined (__SUNPRO_CC) && defined (_RWSTD_VER)
  104. std::locale::id& __get_id (void) const { return id; }
  105. #endif
  106. protected:
  107. virtual ~message_format()
  108. {
  109. }
  110. };
  111. /// \cond INTERNAL
  112. namespace details {
  113. inline bool is_us_ascii_char(char c)
  114. {
  115. // works for null terminated strings regardless char "signness"
  116. return 0<c && c<0x7F;
  117. }
  118. inline bool is_us_ascii_string(char const *msg)
  119. {
  120. while(*msg) {
  121. if(!is_us_ascii_char(*msg++))
  122. return false;
  123. }
  124. return true;
  125. }
  126. template<typename CharType>
  127. struct string_cast_traits {
  128. static CharType const *cast(CharType const *msg,std::basic_string<CharType> &/*unused*/)
  129. {
  130. return msg;
  131. }
  132. };
  133. template<>
  134. struct string_cast_traits<char> {
  135. static char const *cast(char const *msg,std::string &buffer)
  136. {
  137. if(is_us_ascii_string(msg))
  138. return msg;
  139. buffer.reserve(strlen(msg));
  140. char c;
  141. while((c=*msg++)!=0) {
  142. if(is_us_ascii_char(c))
  143. buffer+=c;
  144. }
  145. return buffer.c_str();
  146. }
  147. };
  148. } // details
  149. /// \endcond
  150. ///
  151. /// \brief This class represents a message that can be converted to a specific locale message
  152. ///
  153. /// It holds the original ASCII string that is queried in the dictionary when converting to the output string.
  154. /// The created string may be UTF-8, UTF-16, UTF-32 or other 8-bit encoded string according to the target
  155. /// character type and locale encoding.
  156. ///
  157. template<typename CharType>
  158. class basic_message {
  159. public:
  160. typedef CharType char_type; ///< The character this message object is used with
  161. typedef std::basic_string<char_type> string_type; ///< The string type this object can be used with
  162. typedef message_format<char_type> facet_type; ///< The type of the facet the messages are fetched with
  163. ///
  164. /// Create default empty message
  165. ///
  166. basic_message() :
  167. n_(0),
  168. c_id_(0),
  169. c_context_(0),
  170. c_plural_(0)
  171. {
  172. }
  173. ///
  174. /// Create a simple message from 0 terminated string. The string should exist
  175. /// until the message is destroyed. Generally useful with static constant strings
  176. ///
  177. explicit basic_message(char_type const *id) :
  178. n_(0),
  179. c_id_(id),
  180. c_context_(0),
  181. c_plural_(0)
  182. {
  183. }
  184. ///
  185. /// Create a simple plural form message from 0 terminated strings. The strings should exist
  186. /// until the message is destroyed. Generally useful with static constant strings.
  187. ///
  188. /// \a n is the number, \a single and \a plural are singular and plural forms of the message
  189. ///
  190. explicit basic_message(char_type const *single,char_type const *plural,int n) :
  191. n_(n),
  192. c_id_(single),
  193. c_context_(0),
  194. c_plural_(plural)
  195. {
  196. }
  197. ///
  198. /// Create a simple message from 0 terminated strings, with context
  199. /// information. The string should exist
  200. /// until the message is destroyed. Generally useful with static constant strings
  201. ///
  202. explicit basic_message(char_type const *context,char_type const *id) :
  203. n_(0),
  204. c_id_(id),
  205. c_context_(context),
  206. c_plural_(0)
  207. {
  208. }
  209. ///
  210. /// Create a simple plural form message from 0 terminated strings, with context. The strings should exist
  211. /// until the message is destroyed. Generally useful with static constant strings.
  212. ///
  213. /// \a n is the number, \a single and \a plural are singular and plural forms of the message
  214. ///
  215. explicit basic_message(char_type const *context,char_type const *single,char_type const *plural,int n) :
  216. n_(n),
  217. c_id_(single),
  218. c_context_(context),
  219. c_plural_(plural)
  220. {
  221. }
  222. ///
  223. /// Create a simple message from a string.
  224. ///
  225. explicit basic_message(string_type const &id) :
  226. n_(0),
  227. c_id_(0),
  228. c_context_(0),
  229. c_plural_(0),
  230. id_(id)
  231. {
  232. }
  233. ///
  234. /// Create a simple plural form message from strings.
  235. ///
  236. /// \a n is the number, \a single and \a plural are single and plural forms of the message
  237. ///
  238. explicit basic_message(string_type const &single,string_type const &plural,int number) :
  239. n_(number),
  240. c_id_(0),
  241. c_context_(0),
  242. c_plural_(0),
  243. id_(single),
  244. plural_(plural)
  245. {
  246. }
  247. ///
  248. /// Create a simple message from a string with context.
  249. ///
  250. explicit basic_message(string_type const &context,string_type const &id) :
  251. n_(0),
  252. c_id_(0),
  253. c_context_(0),
  254. c_plural_(0),
  255. id_(id),
  256. context_(context)
  257. {
  258. }
  259. ///
  260. /// Create a simple plural form message from strings.
  261. ///
  262. /// \a n is the number, \a single and \a plural are single and plural forms of the message
  263. ///
  264. explicit basic_message(string_type const &context,string_type const &single,string_type const &plural,int number) :
  265. n_(number),
  266. c_id_(0),
  267. c_context_(0),
  268. c_plural_(0),
  269. id_(single),
  270. context_(context),
  271. plural_(plural)
  272. {
  273. }
  274. ///
  275. /// Copy an object
  276. ///
  277. basic_message(basic_message const &other) :
  278. n_(other.n_),
  279. c_id_(other.c_id_),
  280. c_context_(other.c_context_),
  281. c_plural_(other.c_plural_),
  282. id_(other.id_),
  283. context_(other.context_),
  284. plural_(other.plural_)
  285. {
  286. }
  287. ///
  288. /// Assign other message object to this one
  289. ///
  290. basic_message const &operator=(basic_message const &other)
  291. {
  292. if(this==&other) {
  293. return *this;
  294. }
  295. basic_message tmp(other);
  296. swap(tmp);
  297. return *this;
  298. }
  299. ///
  300. /// Swap two message objects
  301. ///
  302. void swap(basic_message &other)
  303. {
  304. std::swap(n_,other.n_);
  305. std::swap(c_id_,other.c_id_);
  306. std::swap(c_context_,other.c_context_);
  307. std::swap(c_plural_,other.c_plural_);
  308. id_.swap(other.id_);
  309. context_.swap(other.context_);
  310. plural_.swap(other.plural_);
  311. }
  312. ///
  313. /// Message class can be explicitly converted to string class
  314. ///
  315. operator string_type () const
  316. {
  317. return str();
  318. }
  319. ///
  320. /// Translate message to a string in the default global locale, using default domain
  321. ///
  322. string_type str() const
  323. {
  324. std::locale loc;
  325. return str(loc,0);
  326. }
  327. ///
  328. /// Translate message to a string in the locale \a locale, using default domain
  329. ///
  330. string_type str(std::locale const &locale) const
  331. {
  332. return str(locale,0);
  333. }
  334. ///
  335. /// Translate message to a string using locale \a locale and message domain \a domain_id
  336. ///
  337. string_type str(std::locale const &locale,std::string const &domain_id) const
  338. {
  339. int id=0;
  340. if(std::has_facet<facet_type>(locale))
  341. id=std::use_facet<facet_type>(locale).domain(domain_id);
  342. return str(locale,id);
  343. }
  344. ///
  345. /// Translate message to a string using the default locale and message domain \a domain_id
  346. ///
  347. string_type str(std::string const &domain_id) const
  348. {
  349. int id=0;
  350. std::locale loc;
  351. if(std::has_facet<facet_type>(loc))
  352. id=std::use_facet<facet_type>(loc).domain(domain_id);
  353. return str(loc,id);
  354. }
  355. ///
  356. /// Translate message to a string using locale \a loc and message domain index \a id
  357. ///
  358. string_type str(std::locale const &loc,int id) const
  359. {
  360. string_type buffer;
  361. char_type const *ptr = write(loc,id,buffer);
  362. if(ptr == buffer.c_str())
  363. return buffer;
  364. else
  365. buffer = ptr;
  366. return buffer;
  367. }
  368. ///
  369. /// Translate message and write to stream \a out, using imbued locale and domain set to the
  370. /// stream
  371. ///
  372. void write(std::basic_ostream<char_type> &out) const
  373. {
  374. std::locale const &loc = out.getloc();
  375. int id = ios_info::get(out).domain_id();
  376. string_type buffer;
  377. out << write(loc,id,buffer);
  378. }
  379. private:
  380. char_type const *plural() const
  381. {
  382. if(c_plural_)
  383. return c_plural_;
  384. if(plural_.empty())
  385. return 0;
  386. return plural_.c_str();
  387. }
  388. char_type const *context() const
  389. {
  390. if(c_context_)
  391. return c_context_;
  392. if(context_.empty())
  393. return 0;
  394. return context_.c_str();
  395. }
  396. char_type const *id() const
  397. {
  398. return c_id_ ? c_id_ : id_.c_str();
  399. }
  400. char_type const *write(std::locale const &loc,int domain_id,string_type &buffer) const
  401. {
  402. char_type const *translated = 0;
  403. static const char_type empty_string[1] = {0};
  404. char_type const *id = this->id();
  405. char_type const *context = this->context();
  406. char_type const *plural = this->plural();
  407. if(*id == 0)
  408. return empty_string;
  409. facet_type const *facet = 0;
  410. if(std::has_facet<facet_type>(loc))
  411. facet = &std::use_facet<facet_type>(loc);
  412. if(facet) {
  413. if(!plural) {
  414. translated = facet->get(domain_id,context,id);
  415. }
  416. else {
  417. translated = facet->get(domain_id,context,id,n_);
  418. }
  419. }
  420. if(!translated) {
  421. char_type const *msg = plural ? ( n_ == 1 ? id : plural) : id;
  422. if(facet) {
  423. translated = facet->convert(msg,buffer);
  424. }
  425. else {
  426. translated = details::string_cast_traits<char_type>::cast(msg,buffer);
  427. }
  428. }
  429. return translated;
  430. }
  431. /// members
  432. int n_;
  433. char_type const *c_id_;
  434. char_type const *c_context_;
  435. char_type const *c_plural_;
  436. string_type id_;
  437. string_type context_;
  438. string_type plural_;
  439. };
  440. ///
  441. /// Convenience typedef for char
  442. ///
  443. typedef basic_message<char> message;
  444. ///
  445. /// Convenience typedef for wchar_t
  446. ///
  447. typedef basic_message<wchar_t> wmessage;
  448. #ifdef BOOST_LOCALE_ENABLE_CHAR16_T
  449. ///
  450. /// Convenience typedef for char16_t
  451. ///
  452. typedef basic_message<char16_t> u16message;
  453. #endif
  454. #ifdef BOOST_LOCALE_ENABLE_CHAR32_T
  455. ///
  456. /// Convenience typedef for char32_t
  457. ///
  458. typedef basic_message<char32_t> u32message;
  459. #endif
  460. ///
  461. /// Translate message \a msg and write it to stream
  462. ///
  463. template<typename CharType>
  464. std::basic_ostream<CharType> &operator<<(std::basic_ostream<CharType> &out,basic_message<CharType> const &msg)
  465. {
  466. msg.write(out);
  467. return out;
  468. }
  469. ///
  470. /// \anchor boost_locale_translate_family \name Indirect message translation function family
  471. /// @{
  472. ///
  473. /// \brief Translate a message, \a msg is not copied
  474. ///
  475. template<typename CharType>
  476. inline basic_message<CharType> translate(CharType const *msg)
  477. {
  478. return basic_message<CharType>(msg);
  479. }
  480. ///
  481. /// \brief Translate a message in context, \a msg and \a context are not copied
  482. ///
  483. template<typename CharType>
  484. inline basic_message<CharType> translate( CharType const *context,
  485. CharType const *msg)
  486. {
  487. return basic_message<CharType>(context,msg);
  488. }
  489. ///
  490. /// \brief Translate a plural message form, \a single and \a plural are not copied
  491. ///
  492. template<typename CharType>
  493. inline basic_message<CharType> translate( CharType const *single,
  494. CharType const *plural,
  495. int n)
  496. {
  497. return basic_message<CharType>(single,plural,n);
  498. }
  499. ///
  500. /// \brief Translate a plural message from in constext, \a context, \a single and \a plural are not copied
  501. ///
  502. template<typename CharType>
  503. inline basic_message<CharType> translate( CharType const *context,
  504. CharType const *single,
  505. CharType const *plural,
  506. int n)
  507. {
  508. return basic_message<CharType>(context,single,plural,n);
  509. }
  510. ///
  511. /// \brief Translate a message, \a msg is copied
  512. ///
  513. template<typename CharType>
  514. inline basic_message<CharType> translate(std::basic_string<CharType> const &msg)
  515. {
  516. return basic_message<CharType>(msg);
  517. }
  518. ///
  519. /// \brief Translate a message in context,\a context and \a msg is copied
  520. ///
  521. template<typename CharType>
  522. inline basic_message<CharType> translate( std::basic_string<CharType> const &context,
  523. std::basic_string<CharType> const &msg)
  524. {
  525. return basic_message<CharType>(context,msg);
  526. }
  527. ///
  528. /// \brief Translate a plural message form in constext, \a context, \a single and \a plural are copied
  529. ///
  530. template<typename CharType>
  531. inline basic_message<CharType> translate( std::basic_string<CharType> const &context,
  532. std::basic_string<CharType> const &single,
  533. std::basic_string<CharType> const &plural,
  534. int n)
  535. {
  536. return basic_message<CharType>(context,single,plural,n);
  537. }
  538. ///
  539. /// \brief Translate a plural message form, \a single and \a plural are copied
  540. ///
  541. template<typename CharType>
  542. inline basic_message<CharType> translate( std::basic_string<CharType> const &single,
  543. std::basic_string<CharType> const &plural,
  544. int n)
  545. {
  546. return basic_message<CharType>(single,plural,n);
  547. }
  548. /// @}
  549. ///
  550. /// \anchor boost_locale_gettext_family \name Direct message translation functions family
  551. ///
  552. ///
  553. /// Translate message \a id according to locale \a loc
  554. ///
  555. template<typename CharType>
  556. std::basic_string<CharType> gettext(CharType const *id,
  557. std::locale const &loc=std::locale())
  558. {
  559. return basic_message<CharType>(id).str(loc);
  560. }
  561. ///
  562. /// Translate plural form according to locale \a loc
  563. ///
  564. template<typename CharType>
  565. std::basic_string<CharType> ngettext( CharType const *s,
  566. CharType const *p,
  567. int n,
  568. std::locale const &loc=std::locale())
  569. {
  570. return basic_message<CharType>(s,p,n).str(loc);
  571. }
  572. ///
  573. /// Translate message \a id according to locale \a loc in domain \a domain
  574. ///
  575. template<typename CharType>
  576. std::basic_string<CharType> dgettext( char const *domain,
  577. CharType const *id,
  578. std::locale const &loc=std::locale())
  579. {
  580. return basic_message<CharType>(id).str(loc,domain);
  581. }
  582. ///
  583. /// Translate plural form according to locale \a loc in domain \a domain
  584. ///
  585. template<typename CharType>
  586. std::basic_string<CharType> dngettext( char const *domain,
  587. CharType const *s,
  588. CharType const *p,
  589. int n,
  590. std::locale const &loc=std::locale())
  591. {
  592. return basic_message<CharType>(s,p,n).str(loc,domain);
  593. }
  594. ///
  595. /// Translate message \a id according to locale \a loc in context \a context
  596. ///
  597. template<typename CharType>
  598. std::basic_string<CharType> pgettext( CharType const *context,
  599. CharType const *id,
  600. std::locale const &loc=std::locale())
  601. {
  602. return basic_message<CharType>(context,id).str(loc);
  603. }
  604. ///
  605. /// Translate plural form according to locale \a loc in context \a context
  606. ///
  607. template<typename CharType>
  608. std::basic_string<CharType> npgettext( CharType const *context,
  609. CharType const *s,
  610. CharType const *p,
  611. int n,
  612. std::locale const &loc=std::locale())
  613. {
  614. return basic_message<CharType>(context,s,p,n).str(loc);
  615. }
  616. ///
  617. /// Translate message \a id according to locale \a loc in domain \a domain in context \a context
  618. ///
  619. template<typename CharType>
  620. std::basic_string<CharType> dpgettext( char const *domain,
  621. CharType const *context,
  622. CharType const *id,
  623. std::locale const &loc=std::locale())
  624. {
  625. return basic_message<CharType>(context,id).str(loc,domain);
  626. }
  627. ///
  628. /// Translate plural form according to locale \a loc in domain \a domain in context \a context
  629. ///
  630. template<typename CharType>
  631. std::basic_string<CharType> dnpgettext(char const *domain,
  632. CharType const *context,
  633. CharType const *s,
  634. CharType const *p,
  635. int n,
  636. std::locale const &loc=std::locale())
  637. {
  638. return basic_message<CharType>(context,s,p,n).str(loc,domain);
  639. }
  640. ///
  641. /// \cond INTERNAL
  642. ///
  643. template<>
  644. struct BOOST_LOCALE_DECL base_message_format<char> : public std::locale::facet
  645. {
  646. base_message_format(size_t refs = 0) : std::locale::facet(refs)
  647. {
  648. }
  649. static std::locale::id id;
  650. };
  651. template<>
  652. struct BOOST_LOCALE_DECL base_message_format<wchar_t> : public std::locale::facet
  653. {
  654. base_message_format(size_t refs = 0) : std::locale::facet(refs)
  655. {
  656. }
  657. static std::locale::id id;
  658. };
  659. #ifdef BOOST_LOCALE_ENABLE_CHAR16_T
  660. template<>
  661. struct BOOST_LOCALE_DECL base_message_format<char16_t> : public std::locale::facet
  662. {
  663. base_message_format(size_t refs = 0) : std::locale::facet(refs)
  664. {
  665. }
  666. static std::locale::id id;
  667. };
  668. #endif
  669. #ifdef BOOST_LOCALE_ENABLE_CHAR32_T
  670. template<>
  671. struct BOOST_LOCALE_DECL base_message_format<char32_t> : public std::locale::facet
  672. {
  673. base_message_format(size_t refs = 0) : std::locale::facet(refs)
  674. {
  675. }
  676. static std::locale::id id;
  677. };
  678. #endif
  679. /// \endcond
  680. ///
  681. /// @}
  682. ///
  683. namespace as {
  684. /// \cond INTERNAL
  685. namespace details {
  686. struct set_domain {
  687. std::string domain_id;
  688. };
  689. template<typename CharType>
  690. std::basic_ostream<CharType> &operator<<(std::basic_ostream<CharType> &out, set_domain const &dom)
  691. {
  692. int id = std::use_facet<message_format<CharType> >(out.getloc()).domain(dom.domain_id);
  693. ios_info::get(out).domain_id(id);
  694. return out;
  695. }
  696. } // details
  697. /// \endcond
  698. ///
  699. /// \addtogroup manipulators
  700. ///
  701. /// @{
  702. ///
  703. /// Manipulator for switching message domain in ostream,
  704. ///
  705. /// \note The returned object throws std::bad_cast if the I/O stream does not have \ref message_format facet installed
  706. ///
  707. inline
  708. #ifdef BOOST_LOCALE_DOXYGEN
  709. unspecified_type
  710. #else
  711. details::set_domain
  712. #endif
  713. domain(std::string const &id)
  714. {
  715. details::set_domain tmp = { id };
  716. return tmp;
  717. }
  718. /// @}
  719. } // as
  720. } // locale
  721. } // boost
  722. #ifdef BOOST_MSVC
  723. #pragma warning(pop)
  724. #endif
  725. #endif
  726. // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4