You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

702 lines
20 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: stlsoft/util/constraints.hpp (originally MTAlgo.h, ::SynesisStl)
  3. *
  4. * Purpose: Compile-time template constraints templates.
  5. *
  6. * Created: 19th November 1998
  7. * Updated: 11th August 2010
  8. *
  9. * Thanks: To Peter Bannister for having the clear thinking to see the
  10. * obvious (but only in hindsight) tactic of overloading the
  11. * constraints method in must_be_derived.
  12. *
  13. * Home: http://stlsoft.org/
  14. *
  15. * Copyright (c) 1998-2010, Matthew Wilson and Synesis Software
  16. * All rights reserved.
  17. *
  18. * Redistribution and use in source and binary forms, with or without
  19. * modification, are permitted provided that the following conditions are met:
  20. *
  21. * - Redistributions of source code must retain the above copyright notice, this
  22. * list of conditions and the following disclaimer.
  23. * - Redistributions in binary form must reproduce the above copyright notice,
  24. * this list of conditions and the following disclaimer in the documentation
  25. * and/or other materials provided with the distribution.
  26. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  27. * any contributors may be used to endorse or promote products derived from
  28. * this software without specific prior written permission.
  29. *
  30. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  31. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  32. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  34. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  35. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  36. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  37. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  38. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  39. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  40. * POSSIBILITY OF SUCH DAMAGE.
  41. *
  42. * ////////////////////////////////////////////////////////////////////// */
  43. /** \file stlsoft/util/constraints.hpp
  44. *
  45. * \brief [C++ only] Definition of compile-time template constraints
  46. * templates
  47. * (\ref group__library__utility__constraints "Constraints" Library).
  48. */
  49. #ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_CONSTRAINTS
  50. #define STLSOFT_INCL_STLSOFT_UTIL_HPP_CONSTRAINTS
  51. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  52. # define STLSOFT_VER_STLSOFT_UTIL_HPP_CONSTRAINTS_MAJOR 5
  53. # define STLSOFT_VER_STLSOFT_UTIL_HPP_CONSTRAINTS_MINOR 0
  54. # define STLSOFT_VER_STLSOFT_UTIL_HPP_CONSTRAINTS_REVISION 4
  55. # define STLSOFT_VER_STLSOFT_UTIL_HPP_CONSTRAINTS_EDIT 99
  56. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  57. /* /////////////////////////////////////////////////////////////////////////
  58. * Includes
  59. */
  60. #ifndef STLSOFT_INCL_STLSOFT_H_STLSOFT
  61. # include <stlsoft/stlsoft.h>
  62. #endif /* !STLSOFT_INCL_STLSOFT_H_STLSOFT */
  63. #ifndef STLSOFT_INCL_STLSOFT_META_HPP_SIZE_OF
  64. # include <stlsoft/meta/size_of.hpp>
  65. #endif /* !STLSOFT_INCL_STLSOFT_META_HPP_SIZE_OF */
  66. /* /////////////////////////////////////////////////////////////////////////
  67. * Namespace
  68. */
  69. #ifndef _STLSOFT_NO_NAMESPACE
  70. namespace stlsoft
  71. {
  72. #endif /* _STLSOFT_NO_NAMESPACE */
  73. /* /////////////////////////////////////////////////////////////////////////
  74. * Macros
  75. */
  76. #if defined(STLSOFT_COMPILER_IS_BORLAND) || \
  77. defined(STLSOFT_COMPILER_IS_INTEL) || \
  78. defined(STLSOFT_COMPILER_IS_MWERKS)
  79. # define stlsoft_constraint_must_be_pod(T) do { stlsoft_ns_qual(must_be_pod)<T>::func_ptr_type const pfn = stlsoft_ns_qual(must_be_pod)<T>::constraint(); STLSOFT_SUPPRESS_UNUSED(pfn); } while(0)
  80. # define stlsoft_constraint_must_be_pod_or_void(T) do { stlsoft_ns_qual(must_be_pod_or_void)<T>::func_ptr_type const pfn = stlsoft_ns_qual(must_be_pod_or_void)<T>::constraint(); STLSOFT_SUPPRESS_UNUSED(pfn); } while(0)
  81. #elif defined(STLSOFT_COMPILER_IS_DMC)
  82. # define stlsoft_constraint_must_be_pod(T) do { int i = sizeof(stlsoft_ns_qual(must_be_pod)<T>::constraint()); } while(0)
  83. # define stlsoft_constraint_must_be_pod_or_void(T) do { int i = sizeof(stlsoft_ns_qual(must_be_pod_or_void)<T>::constraint()); } while(0)
  84. #else /* ? compiler */
  85. # define stlsoft_constraint_must_be_pod(T) STLSOFT_STATIC_ASSERT(sizeof(stlsoft_ns_qual(must_be_pod)<T>::constraint()) != 0)
  86. # define stlsoft_constraint_must_be_pod_or_void(T) STLSOFT_STATIC_ASSERT(sizeof(stlsoft_ns_qual(must_be_pod_or_void)<T>::constraint()) != 0)
  87. #endif /* compiler */
  88. # define stlsoft_constraint_must_be_same_size(T1, T2) static_cast<void>(stlsoft_ns_qual(must_be_same_size)<T1, T2>())
  89. # define stlsoft_constraint_must_be_subscriptable(T) static_cast<void>(stlsoft_ns_qual(must_be_subscriptable)<T>())
  90. # define stlsoft_constraint_must_have_base(D, B) static_cast<void>(stlsoft_ns_qual(must_have_base)<D, B>())
  91. # define stlsoft_constraint_must_be_derived(D, B) static_cast<void>(stlsoft_ns_qual(must_be_derived)<D, B>())
  92. /* /////////////////////////////////////////////////////////////////////////
  93. * Constraints
  94. */
  95. /** \brief Constraint to ensure that the one type is convertible to another via inheritance
  96. *
  97. * \ingroup group__library__utility__constraints
  98. *
  99. * \param D The derived type
  100. * \param B The base type
  101. *
  102. * It may be used as follows:
  103. \code
  104. class Parent {};
  105. class Child : public Parent {};
  106. class Orphan {};
  107. stlsoft::must_have_base<Parent, Parent>(); // Ok
  108. stlsoft::must_have_base<Child, Parent>(); // Ok
  109. stlsoft::must_have_base<Child, Child>(); // Ok
  110. stlsoft::must_have_base<Child, Parent>(); // Compile error!
  111. stlsoft::must_have_base<Orphan, Parent>(); // Compile error!
  112. stlsoft::must_have_base<Orphan, Child>(); // Compile error!
  113. stlsoft::must_have_base<Parent, Orphan>(); // Compile error!
  114. stlsoft::must_have_base<Child, Orphan>(); // Compile error!
  115. \endcode
  116. *
  117. * \note This is borrowed from Bjarne Stroustrup's idea as posted to comp.lang.c++.moderated
  118. * 17th February 2001.
  119. *
  120. * \see stlsoft::must_be_derived
  121. */
  122. // [[synesis:class:constraint:must_have_base<T<D>, T<B>>]]
  123. template< ss_typename_param_k D
  124. , ss_typename_param_k B
  125. >
  126. struct must_have_base
  127. {
  128. public:
  129. ~must_have_base() stlsoft_throw_0()
  130. {
  131. void(*p)(D*, B*) = constraints;
  132. STLSOFT_SUPPRESS_UNUSED(p);
  133. }
  134. private:
  135. static void constraints(D* pd, B* pb)
  136. {
  137. pb = pd;
  138. STLSOFT_SUPPRESS_UNUSED(pb);
  139. }
  140. };
  141. /** \brief Constraint to ensure that the one type is convertible to another via inheritance,
  142. * but is not the same type
  143. *
  144. * \ingroup group__library__utility__constraints
  145. *
  146. * \param D The derived type
  147. * \param B The base type
  148. *
  149. * It may be used as follows:
  150. \code
  151. class Parent {};
  152. class Child : public Parent {};
  153. class Orphan {};
  154. stlsoft::must_be_derived<Parent, Parent>(); // Compile error!
  155. stlsoft::must_be_derived<Child, Parent>(); // Ok
  156. stlsoft::must_be_derived<Child, Child>(); // Compile error!
  157. stlsoft::must_have_base<Child, Parent>(); // Compile error!
  158. stlsoft::must_be_derived<Orphan, Parent>(); // Compile error!
  159. stlsoft::must_be_derived<Orphan, Child>(); // Compile error!
  160. stlsoft::must_be_derived<Parent, Orphan>(); // Compile error!
  161. stlsoft::must_be_derived<Child, Orphan>(); // Compile error!
  162. \endcode
  163. *
  164. * \note This extension to the must_have_base constraint was proposed by
  165. * Peter Bannister after reading Chapter 1 of \ref section__publishing__books__imperfectcplusplus.
  166. *
  167. * \see stlsoft::must_have_base
  168. */
  169. // [[synesis:class:constraint:must_be_derived<T<D>, T<B>>]]
  170. template< ss_typename_param_k D
  171. , ss_typename_param_k B
  172. >
  173. struct must_be_derived
  174. {
  175. public:
  176. ~must_be_derived() stlsoft_throw_0()
  177. {
  178. # if defined(STLSOFT_COMPILER_IS_BORLAND)
  179. cant_be_overloaded_if_same_type(static_cast<D*>(0)
  180. , static_cast<B*>(0));
  181. # else /* ? compiler */
  182. void(*p)(D*, B*) = cant_be_overloaded_if_same_type;
  183. STLSOFT_SUPPRESS_UNUSED(p);
  184. # endif /* compiler */
  185. }
  186. private:
  187. static void cant_be_overloaded_if_same_type(D* pd, B* pb)
  188. {
  189. pb = pd;
  190. STLSOFT_SUPPRESS_UNUSED(pb);
  191. }
  192. static void cant_be_overloaded_if_same_type(B* pb, D* pd)
  193. {
  194. pb = pd;
  195. STLSOFT_SUPPRESS_UNUSED(pb);
  196. }
  197. };
  198. /** \brief Constrains two types to be of the same size
  199. *
  200. * \ingroup group__library__utility__constraints
  201. *
  202. * \param T1 The first type
  203. * \param T2 The second type
  204. *
  205. * It may be used as follows:
  206. \code
  207. stlsoft::must_be_same_size<long, long>(); // Ok
  208. stlsoft::must_be_same_size<char, long>(); // Compile error!
  209. stlsoft::must_be_same_size<long, char>(); // Compile error!
  210. \endcode
  211. *
  212. */
  213. // [[synesis:class:constraint:must_be_same_size<T<T1>, T<T2>>]]
  214. template< ss_typename_param_k T1
  215. , ss_typename_param_k T2
  216. >
  217. struct must_be_same_size
  218. {
  219. ~must_be_same_size() stlsoft_throw_0()
  220. {
  221. void (*pfn)(void) = constraints;
  222. STLSOFT_SUPPRESS_UNUSED(pfn);
  223. }
  224. private:
  225. static void constraints()
  226. {
  227. // The compiler will bring you here if T1 and T2 are not the same
  228. // size.
  229. struct must_be_same_size_
  230. {
  231. int T1_must_be_same_size_as_T2 : (static_cast<int>(size_of<T1>::value) == static_cast<int>(size_of<T2>::value));
  232. };
  233. const int T1_must_be_same_size_as_T2 = (static_cast<int>(size_of<T1>::value) == static_cast<int>(size_of<T2>::value));
  234. int i[T1_must_be_same_size_as_T2];
  235. STLSOFT_SUPPRESS_UNUSED(i);
  236. }
  237. };
  238. /** \brief Constraint to enforce that a given type is an array, or pointer, or user defined type
  239. * which is amenable to subsripting (i.e. defines <code>operator[]</code> or <code>operator X*()</code>)
  240. *
  241. * \ingroup group__library__utility__constraints
  242. *
  243. * \param T The type to be constrained
  244. *
  245. * It may be used as follows:
  246. \code
  247. typedef std::vector<int> vec_t;
  248. stlsoft::must_be_subscriptable<int*>(); // Ok
  249. stlsoft::must_be_subscriptable<vec_t>(); // Ok
  250. stlsoft::must_be_subscriptable<double>(); // Compile error!
  251. \endcode
  252. *
  253. * \see stlsoft::must_subscript_as_decayable_pointer
  254. */
  255. // [[synesis:class:constraint:must_be_subscriptable<T<T>>]]
  256. template <ss_typename_param_k T>
  257. struct must_be_subscriptable
  258. {
  259. public:
  260. ~must_be_subscriptable() stlsoft_throw_0()
  261. {
  262. int (*pfn)(T const&) = constraints;
  263. STLSOFT_SUPPRESS_UNUSED(pfn);
  264. }
  265. private:
  266. static int constraints(T const& T_is_not_subscriptable)
  267. {
  268. // The compiler will bring you here if T is not subscriptable
  269. return sizeof(T_is_not_subscriptable[0]);
  270. }
  271. };
  272. /** \brief Constraint to enforce that a given type is an actual array or pointer, rather than
  273. * a user-defined type with a subscript operator.
  274. *
  275. * \ingroup group__library__utility__constraints
  276. *
  277. * \param T The type to be constrained
  278. *
  279. * It may be used as follows:
  280. \code
  281. typedef std::vector<int> vec_t;
  282. stlsoft::must_subscript_as_decayable_pointer<int*>(); // Ok
  283. stlsoft::must_subscript_as_decayable_pointer<vec_t>(); // Compile error!
  284. stlsoft::must_subscript_as_decayable_pointer<double>(); // Compile error!
  285. \endcode
  286. *
  287. * \see stlsoft::must_be_subscriptable
  288. */
  289. // [[synesis:class:constraint:must_subscript_as_decayable_pointer<T<T>>]]
  290. template <ss_typename_param_k T>
  291. struct must_subscript_as_decayable_pointer
  292. {
  293. public:
  294. ~must_subscript_as_decayable_pointer() stlsoft_throw_0()
  295. {
  296. ss_size_t (*pfn)(T const&) = constraints;
  297. STLSOFT_SUPPRESS_UNUSED(pfn);
  298. }
  299. private:
  300. static ss_size_t constraints(T const& T_is_not_decay_subscriptable)
  301. {
  302. // The compiler will bring you here if T has a user-defined
  303. // subscript operator.
  304. return sizeof(0[T_is_not_decay_subscriptable]);
  305. }
  306. };
  307. /** \brief Constraint to ensure that a type is a built-in or trivial type.
  308. *
  309. * \ingroup group__library__utility__constraints
  310. *
  311. * \param T The type to be constrained
  312. *
  313. * This class can be used to constrain a type to be of either built-in, e.g.
  314. * int, or of a trivial type, i.e. aggregate types or types with publicly
  315. * accessible default contructors and assignment operators.
  316. *
  317. * It may be used as follows:
  318. \code
  319. typedef std::vector<int> vec_t;
  320. stlsoft::must_be_pod<int*>(); // Ok
  321. stlsoft::must_be_pod<vec_t>(); // Compile error!
  322. stlsoft::must_be_pod<double>(); // Ok
  323. stlsoft::must_be_pod<void>(); // Compile error!
  324. \endcode
  325. *
  326. * \see stlsoft::must_be_pod_or_void
  327. */
  328. // [[synesis:class:constraint:must_be_pod<T<T>>]]
  329. template <ss_typename_param_k T>
  330. union must_be_pod
  331. {
  332. private:
  333. typedef must_be_pod<T> class_type;
  334. public:
  335. T t;
  336. int i;
  337. typedef int (*func_ptr_type)();
  338. static func_ptr_type constraint()
  339. {
  340. return constraints;
  341. }
  342. // Required by CodeWarrior
  343. must_be_pod()
  344. {}
  345. // Required by CodeWarrior
  346. ~must_be_pod() stlsoft_throw_0()
  347. {
  348. int (*pfn)(void) = constraints;
  349. STLSOFT_SUPPRESS_UNUSED(pfn);
  350. }
  351. private:
  352. #if !defined(STLSOFT_COMPILER_IS_MWERKS)
  353. must_be_pod(class_type const&);
  354. class_type& operator =(class_type const&);
  355. #endif
  356. private:
  357. static int constraints()
  358. {
  359. #if defined(STLSOFT_COMPILER_IS_MWERKS)
  360. # if ((__MWERKS__ & 0xFF00) < 0x3000)
  361. class_type u;
  362. # else /* ? compiler */
  363. class_type u;
  364. u = *static_cast<class_type*>(0);
  365. # endif /* compiler */
  366. #elif defined(STLSOFT_COMPILER_IS_GCC) && \
  367. __GNUC__ < 3
  368. class_type u = *static_cast<class_type*>(0);
  369. #else /* ? compiler */
  370. class_type u = class_type();
  371. #endif /* compiler */
  372. STLSOFT_SUPPRESS_UNUSED(u);
  373. return sizeof(u);
  374. }
  375. };
  376. /** \brief Constraint to ensure that a type is a built-in or trivial type,
  377. * or is \c void.
  378. *
  379. * \ingroup group__library__utility__constraints
  380. *
  381. * \param T The type to be constrained
  382. *
  383. * This class can be used to constrain a type to be of either built-in, e.g.
  384. * int, or of a trivial type, i.e. aggregate types or types with publicly
  385. * accessible default contructors and assignment operators, or \c void.
  386. *
  387. * It may be used as follows:
  388. \code
  389. typedef std::vector<int> vec_t;
  390. stlsoft::must_be_pod_or_void<int*>(); // Ok
  391. stlsoft::must_be_pod_or_void<vec_t>(); // Compile error!
  392. stlsoft::must_be_pod_or_void<double>(); // Ok
  393. stlsoft::must_be_pod_or_void<void>(); // Ok
  394. \endcode
  395. *
  396. * \see stlsoft::must_be_pod
  397. */
  398. // [[synesis:class:constraint:must_be_pod_or_void<T<T>>]]
  399. template <ss_typename_param_k T>
  400. union must_be_pod_or_void
  401. {
  402. private:
  403. typedef must_be_pod_or_void<T> class_type;
  404. public:
  405. T t;
  406. int i;
  407. typedef int (*func_ptr_type)();
  408. static func_ptr_type constraint()
  409. {
  410. return constraints;
  411. }
  412. #if defined(STLSOFT_CF_COMPILER_WARNS_NO_PUBLIC_DTOR)
  413. protected:
  414. #else /* ? STLSOFT_CF_COMPILER_WARNS_NO_PUBLIC_DTOR */
  415. private:
  416. #endif /* STLSOFT_CF_COMPILER_WARNS_NO_PUBLIC_DTOR */
  417. static int constraints()
  418. {
  419. class_type u;
  420. u.i = 1; // CodeWarrior requires this
  421. STLSOFT_SUPPRESS_UNUSED(u);
  422. return sizeof(u);
  423. }
  424. };
  425. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  426. STLSOFT_TEMPLATE_SPECIALISATION
  427. union must_be_pod_or_void<void>
  428. {
  429. typedef int (*func_ptr_type)();
  430. static func_ptr_type constraint()
  431. {
  432. return static_cast<func_ptr_type>(0); // Can't use NULL here, as Intel C++ gets snippy with NULL_v
  433. }
  434. };
  435. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  436. /* ////////////////////////////////////////////////////////////////////// */
  437. #if 0
  438. /** \brief This type is used as a tag parent to hide implicit comparison of types that
  439. * provide implicit converion operators.
  440. *
  441. * \ingroup group__library__utility__constraints
  442. *
  443. */
  444. #ifdef NIC_TEMPLATE_VERSION
  445. //struct nic_null_
  446. //{};
  447. typedef void nic_null_;
  448. template <ss_typename_param_k T = nic_null_>
  449. struct not_implicitly_comparable
  450. : public T
  451. {
  452. public:
  453. typedef not_implicitly_comparable<T> class_type;
  454. #if defined(STLSOFT_CF_COMPILER_WARNS_NO_PUBLIC_DTOR)
  455. protected:
  456. #else /* ? STLSOFT_CF_COMPILER_WARNS_NO_PUBLIC_DTOR */
  457. private:
  458. #endif /* STLSOFT_CF_COMPILER_WARNS_NO_PUBLIC_DTOR */
  459. #if 0
  460. template <ss_typename_param_k T2>
  461. ss_bool_t operator ==(T2 const&) const;
  462. template <ss_typename_param_k T2>
  463. ss_bool_t operator !=(T2 const&) const;
  464. #endif /* 0 */
  465. };
  466. /** \brief This specialisation allows it to
  467. *
  468. * \ingroup group__library__utility__constraints
  469. *
  470. */
  471. STLSOFT_TEMPLATE_SPECIALISATION
  472. struct not_implicitly_comparable<nic_null_>
  473. {
  474. public:
  475. typedef not_implicitly_comparable<nic_null_> class_type;
  476. #if defined(STLSOFT_CF_COMPILER_WARNS_NO_PUBLIC_DTOR)
  477. protected:
  478. #else /* ? STLSOFT_CF_COMPILER_WARNS_NO_PUBLIC_DTOR */
  479. private:
  480. #endif /* STLSOFT_CF_COMPILER_WARNS_NO_PUBLIC_DTOR */
  481. #if 0
  482. template <ss_typename_param_k T2>
  483. ss_bool_t operator ==(T2 const&) const;
  484. template <ss_typename_param_k T2>
  485. ss_bool_t operator !=(T2 const&) const;
  486. #endif /* 0 */
  487. };
  488. template< ss_typename_param_k T
  489. , ss_typename_param_k T2
  490. >
  491. inline ss_bool_t operator ==(not_implicitly_comparable<T> const& lhs, T2 const& rhs)
  492. {
  493. // return lhs.operator ==(rhs);
  494. lhs.this_type_does_not_support_comparisons();
  495. return false; // Placate the eager beavers
  496. }
  497. template< ss_typename_param_k T
  498. , ss_typename_param_k T2
  499. >
  500. inline ss_bool_t operator ==(T2 const& lhs, not_implicitly_comparable<T> const& rhs)
  501. {
  502. // return rhs.operator ==(lhs);
  503. rhs.this_type_does_not_support_comparisons();
  504. return false; // Placate the eager beavers
  505. }
  506. #if 0
  507. template< ss_typename_param_k T1
  508. , ss_typename_param_k T2
  509. >
  510. inline ss_bool_t operator ==(not_implicitly_comparable<T1> const& lhs, not_implicitly_comparable<T2> const& rhs)
  511. {
  512. // return rhs.operator ==(lhs);
  513. rhs.this_type_does_not_support_comparisons();
  514. return false; // Placate the eager beavers
  515. }
  516. #endif /* 0 */
  517. template< ss_typename_param_k T
  518. , ss_typename_param_k T2
  519. >
  520. inline ss_bool_t operator !=(T2 const& lhs, not_implicitly_comparable<T> const& rhs)
  521. {
  522. // return rhs.operator !=(lhs);
  523. rhs.this_type_does_not_support_comparisons();
  524. return false; // Placate the eager beavers
  525. }
  526. template< ss_typename_param_k T
  527. , ss_typename_param_k T2
  528. >
  529. inline ss_bool_t operator !=(not_implicitly_comparable<T> const& lhs, T2 const& rhs)
  530. {
  531. // return lhs.operator !=(rhs);
  532. lhs.this_type_does_not_support_comparisons();
  533. return false; // Placate the eager beavers
  534. }
  535. template< ss_typename_param_k T1
  536. , ss_typename_param_k T2
  537. >
  538. inline ss_bool_t operator !=(not_implicitly_comparable<T1> const& lhs, not_implicitly_comparable<T2> const& rhs)
  539. {
  540. // return lhs.operator !=(rhs);
  541. lhs.this_type_does_not_support_comparisons();
  542. return false; // Placate the eager beavers
  543. }
  544. #else /* ? 0 */
  545. struct not_implicitly_comparable
  546. {
  547. public:
  548. typedef not_implicitly_comparable class_type;
  549. #if defined(STLSOFT_CF_COMPILER_WARNS_NO_PUBLIC_DTOR)
  550. protected:
  551. #else /* ? STLSOFT_CF_COMPILER_WARNS_NO_PUBLIC_DTOR */
  552. private:
  553. #endif /* STLSOFT_CF_COMPILER_WARNS_NO_PUBLIC_DTOR */
  554. #ifndef NIC_EXTERNAL_OPERATORS
  555. ss_bool_t operator ==(class_type const&) const;
  556. ss_bool_t operator !=(class_type const&) const;
  557. template <ss_typename_param_k T2>
  558. ss_bool_t operator ==(T2 const&) const;
  559. template <ss_typename_param_k T2>
  560. ss_bool_t operator !=(T2 const&) const;
  561. #endif /* !NIC_EXTERNAL_OPERATORS */
  562. };
  563. #ifdef NIC_EXTERNAL_OPERATORS
  564. template< ss_typename_param_k T2
  565. >
  566. inline ss_bool_t operator ==(not_implicitly_comparable const& lhs, T2 const& rhs)
  567. {
  568. // return lhs.operator ==(rhs);
  569. lhs.this_type_does_not_support_comparisons();
  570. return false; // Placate the eager beavers
  571. }
  572. template< ss_typename_param_k T2
  573. >
  574. inline ss_bool_t operator ==(T2 const& lhs, not_implicitly_comparable const& rhs)
  575. {
  576. // return rhs.operator ==(lhs);
  577. rhs.this_type_does_not_support_comparisons();
  578. return false; // Placate the eager beavers
  579. }
  580. #endif /* NIC_EXTERNAL_OPERATORS */
  581. #endif /* 0 */
  582. #endif /* 0 */
  583. /* ////////////////////////////////////////////////////////////////////// */
  584. #ifndef _STLSOFT_NO_NAMESPACE
  585. } // namespace stlsoft
  586. #endif /* _STLSOFT_NO_NAMESPACE */
  587. /* ////////////////////////////////////////////////////////////////////// */
  588. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_HPP_CONSTRAINTS */
  589. /* ///////////////////////////// end of file //////////////////////////// */