Compare commits

...

194 Commits

Author SHA1 Message Date
e8c2d8a124 Rework as esp-idf component 2023-11-23 17:17:05 +01:00
5656ffe0ac re-enable mingw appveyor ci testing 2022-04-24 20:56:09 -04:00
3b2dbfea08 [issue-24] test failure for new clang-win ci job 2022-04-24 08:38:17 -04:00
772c1b40c8 align with boost-ci 2022.02 and GitHub Actions 2022-04-24 08:38:17 -04:00
9c89e99629 Update GitHub Actions CI file (#33) 2021-08-04 07:07:30 -07:00
e34c735a1a Update CMakeLists.txt 2021-06-10 01:19:53 +03:00
85fd1e434f Fix MSVC 'unused return' warning; Addresses #31 2021-03-09 06:51:48 -08:00
99901a98fd Add GitHub Actions config [ci skip] (#32) 2021-03-03 18:23:40 -08:00
c5ecc3bb3a add drone config [ci skip] (#29) 2021-03-03 18:23:28 -08:00
affc79e045 Ignore -Wnonnull new gcc 11 warnings. (#28) 2021-03-03 18:23:14 -08:00
feb8accc6e [skip ci] Add "cxxstd" json field. The "cxxstd" json field is being added to each Boost library's meta json information for libraries in order to specify the minumum C++ standard compilation level. The value of this field matches one of the values for 'cxxstd' in Boost.Build. The purpose of doing this is to provide information for the Boost website documentation for each library which will specify the minimum C++ standard compilation that an end-user must employ in order to use the particular library. This will aid end-users who want to know if they can successfully use a Boost library based on their C++ compiler's compilation level, without having to search the library's documentation to find this out. (#30) 2021-01-21 02:13:02 -05:00
a8cf003d4a Removed usage of deprecated header boost/detail/iterator.hpp. (#26)
This header was deprecated in favor of <iterator>. It generates compiler
warnings and will be removed in a future release.
2020-06-24 09:50:46 -07:00
e69c81326d Change __BORLANDC__ to BOOST_BORLANDC, which is defined in Boost config for the Embarcadero non-clang-based compilers. (#25) 2020-04-16 07:52:36 -07:00
db1f9c73a4 Update CI 2019-04-27 06:07:52 -04:00
b9c73e191b ignore unused variable in test (fix matrix warning) 2019-02-19 21:13:39 -05:00
bc2482b38f Removed expected failure for stl_concept_covering
It was marked for all toolsets for some reason.
741a03ba0b
2019-02-19 07:09:33 -05:00
7dbaa85413 Disable random_shuffle test in C++17 mode (it was removed) 2018-11-06 08:54:53 -05:00
eeeb60b797 Expand CI with libc++ build and VS2017 strict 2018-11-06 08:54:53 -05:00
c2723f984c expand ci coverage 2018-10-27 21:27:31 -04:00
0d65b45953 Merge pull request #18 from CromwellEnage/doc_stl_links
Fix broken links in documentation.
2018-10-13 12:15:51 -04:00
0381c5fc54 Fix broken links in documentation.
Some documentation links currently point to pages that HP retired along with the rest of the SGI STL website. These links now point to the Boost mirror site.
2018-10-11 12:33:49 -04:00
64e72828d7 concept_check: misc. typos
Found via `codespell -q 3`
2018-09-26 14:25:39 -04:00
bd8faa928d Fixed <boost/concept_archetype.hpp>
Added missing #include <boost/config/workaround.hpp> which defines BOOST_WORKAROUND.
2018-09-21 13:37:40 -04:00
8847e4b104 Add minimal CMakeLists.txt 2018-09-20 09:01:08 -04:00
ee943d0f7c Merge pull request #14 from boostorg/dependency
Drop dependency on Boost.Mpl
2018-09-09 09:14:34 -07:00
bbf48ff290 Drop dependency on Boost.Mpl 2018-09-08 09:50:42 -04:00
7226a74471 Merge branch 'master' into develop 2018-08-13 21:44:29 +00:00
5e14874d04 fix readme badges and links for appveyor and covscan 2018-07-23 17:13:08 +00:00
376201b10d Add CI framework
- travis with valgrind, cppcheck, ubsan, codecov, covscan (future)
  - appveyor with MSVC 2010 through 2017, cygwin 32/64, mingw 32/64
  - README, LICENSE, etc.
2018-07-23 13:07:11 -04:00
ed0a0ebd72 Merge branch 'develop' 2018-02-20 08:36:45 -05:00
db9894fa8b Merge pull request #11 from DanielaE/feature/retire-header-iterator
Get rid of iterator.hpp
2017-12-28 23:27:40 -05:00
8deb5d203c Get rid of iterator.hpp
It does nothing more than pulling 'std::iterator' into namespace boost and including standard libraries 'iterator' and 'cstddef'. This library only takes advantage of the included headers. OTOH, pulling 'std::iterator' into boost generates deprecation warnings in MSVC 14.1 when compiling in C++17 mode. Besides that, Boost's 'iterator.hpp' is deprecated, too.

Signed-off-by: Daniela Engert <dani@ngrt.de>
2017-12-27 15:51:22 +01:00
00496f2010 Minor doc updates 2017-04-06 08:19:52 -07:00
df4ced9aae Merge pull request #10 from eldiener/develop
Some minor documentation fixes.
2017-04-04 08:20:40 -04:00
3df02ba00e Correction of previous fix. 2017-04-04 08:12:27 -04:00
06b61f5407 Some doc corrections. 2017-04-04 07:59:25 -04:00
3397b4df48 Merge branch 'master' into develop 2017-01-04 11:57:51 -05:00
b65104932a Add, and update, documentation build targets. 2016-10-10 11:39:48 -05:00
463edb00e4 Add, and update, documentation build targets. 2016-10-07 23:07:33 -05:00
28b219981e Merge to master for 1.62.0 release 2016-08-17 13:04:04 -07:00
c7d61df2af Merge pull request #9 from danieljames/move-tests
This looks fine to me.  I'll watch the test bots, and merge to master in a week or so.
2016-07-01 08:23:52 -07:00
ec560ba5b0 Dummy jamfile for the super project's build script. 2016-07-01 08:55:18 +01:00
6284402a2d Move tests into subdirectory 2016-07-01 08:47:30 +01:00
504ea0b18d Merge branch 'develop' 2015-10-15 03:01:47 -04:00
a2e63dad4c Merge pull request #8 from MarcelRaad/patch-1
Remove deprecated includes
2015-09-17 08:24:36 -04:00
671bbfdb0f Remove deprecated includes
A comment in boost/iterator.hpp and boost/detail/iterator.hpp mentions that the files are obsolete and will be deprecated. All they do is pull some types from namespace std into namespace boost. boost/iterator.hpp isn't used anyway.
2015-09-13 21:51:19 +02:00
80cfac7881 Merge to master for 1.59.0 release 2015-07-22 10:50:36 -07:00
acc3cd0ea2 Merge branch 'master' into develop 2015-05-20 10:26:39 -07:00
bdcd06c4cc Use BOOST_ATTRIBUTE_UNUSED from boost/config 2015-05-20 10:23:35 -07:00
89eb7b4cdc Merge changes from develop for the 1.58.0 release 2015-04-01 10:28:04 -07:00
bb9257a37e Remove executable status from a bunch of source files 2014-11-24 13:55:31 -08:00
92a156c79d Merge pull request #3 from danieljames/metadata
Create metadata file.
2014-11-02 15:29:52 -07:00
0d5bfc869c Add metadata file. 2014-08-18 14:57:53 +01:00
b708baa8ed Remove include of boost/parameter/aux_/parenthesized_type.hpp. 2014-06-10 22:18:34 +03:00
50574588ae Remove include of boost/parameter/aux_/parenthesized_type.hpp. 2014-06-09 04:29:52 +03:00
d6a527bb21 Merge branch 'develop'
Apply some fixes from develop.
2014-05-11 10:43:16 -06:00
f2c369a6c3 Merge branch 'master' into develop 2014-05-11 10:43:01 -06:00
e7ca7744c4 Fix for Ticket #2628.
Sequence containers are not required to have a size_type constructor.
The standard only requires that sequences have an
S(size_type, value_type) constructor.
2014-02-18 22:36:30 -08:00
6784696095 Fix broken concept build.
The stl_concept_covering.cpp file only works with __GNUC__ or __KCC.
2014-02-18 22:16:42 -08:00
cde699f812 Merge pull request #1 from ahmedcharles/develop
Remove out-dated/unused/duplicate files.
2014-02-18 20:37:11 -08:00
90b0397f54 Remove out-dated/unused/duplicate files. 2014-02-08 21:24:44 -08:00
d2d56f6de8 Merge warning fixes from develop. 2013-12-08 11:23:31 +00:00
389bf0d089 Create merge point from git. 2013-12-08 11:20:36 +00:00
ccd9f52467 Supress msvc warnings. Fixes #5102.
[SVN r71053]
2013-12-08 11:19:29 +00:00
229e3055a0 Suppress warnings on msvc 10.
[SVN r70699]
2013-12-08 11:19:23 +00:00
36701c51ab Concept: Remove obsolete GCC version check.
[SVN r86107]
2013-10-01 08:42:50 +00:00
dd7163b7f0 Concept: Remove obsolete GCC version checks.
[SVN r86057]
2013-09-30 15:54:47 +00:00
724b43f885 Concept: Remove obsolete MSVC version checks.
[SVN r86023]
2013-09-30 00:18:01 +00:00
168e60aa3d Added unused attribute for new versions of GCC
[SVN r84470]
2013-05-25 02:11:20 +00:00
9521991561 Concept: fix minor warning.
[SVN r83983]
2013-04-20 14:02:02 +00:00
590fed825c [concept_check] "Shadowed variable warning" (fixes #6738)
[SVN r78702]
2012-05-28 07:56:11 +00:00
38154ae6cf [concept_check] "Shadowed variable warning" (refs #6738)
[SVN r78501]
2012-05-18 02:58:12 +00:00
da5ab9b807 Merged r76050, r75547, r75891, r76049, r76083, and r76439 from trunk (reverse_graph bug fixes and fix for #6293); refs #6293
[SVN r76535]
2012-01-15 23:32:09 +00:00
60b5eb331c Applied fixed version of patch from #6293; fixes #6293
[SVN r76050]
2011-12-18 21:09:34 +00:00
52adefee9a Supress msvc warnings. Fixes #5102.
[SVN r71053]
2011-04-06 22:26:42 +00:00
d78b6bae1c Suppress warnings on msvc 10.
[SVN r70699]
2011-03-29 15:14:53 +00:00
a16e4a65da Stop using BOOST_NO_CONCEPTS macro as it's going to be removed from Boost.Config.
[SVN r70473]
2011-03-23 12:20:49 +00:00
d66a39d4fc Change to use BOOST_HAS_CONCEPTS since BOOST_NO_CONCEPTS has been removed (it's been dropped from the standard).
[SVN r70000]
2011-03-15 12:54:46 +00:00
7dec68923d Merging fixes to release; fixes #2294 fixes #4918 fixes #3645 refs #2823 refs #1427 refs #2893
[SVN r67792]
2011-01-08 18:38:08 +00:00
15afb20c84 Applied patch - refs #4918; will merge to release after tests cycle
[SVN r67742]
2011-01-07 00:23:47 +00:00
b4ff615db8 Eliminate warnings from BinaryFunction, UnaryPredicate, BinaryPredicate concept check classes.
[SVN r67422]
2010-12-23 00:43:10 +00:00
807fcd7b97 Merged r47768 (new example) and r62611 (fix for bug #4032) from trunk; refs #4032
[SVN r65770]
2010-10-05 18:15:27 +00:00
45d722b5c3 Merge documentation fixes.
* Use `doc/src/*.css` instead of `doc/html/*.css`.
* Remove wiki and people directories.
* Some documentation fixes.
* Left out `minimal.css` changes and boostbook changes because of clashes.


[SVN r63347]
2010-06-26 12:30:09 +00:00
f81493caa1 Update various libraries' documentation build.
Mostly to use the images and css files under doc/src instead of
doc/html, usually be deleting the settings in order to use the defaults.
Also add 'boost.root' to some builds in order to fix links which rely on
it.

[SVN r63146]
2010-06-20 18:00:48 +00:00
a1772df31b Added char as an integral type; fixes #2629
[SVN r62612]
2010-06-08 23:37:21 +00:00
d4658af6d7 Moved Collection concept into Boost.ConceptCheck; moved other MultiArray concepts into boost::multi_array_concepts and documented them in reference.xml (do not know how to rebuild HTML from that); fixes #4032
[SVN r62611]
2010-06-08 23:28:23 +00:00
570d5a6f92 Merged r53751, r41955, r47793, r47794, r47797, r62595 from trunk; fixes #865
[SVN r62596]
2010-06-08 19:31:13 +00:00
7e0926d77f Fixed typo in comment
[SVN r62595]
2010-06-08 19:23:09 +00:00
def441d02d Merged revisions 61152,61185 via svnmerge from
https://svn.boost.org/svn/boost/trunk

........
  r61152 | jhunold | 2010-04-09 11:04:51 +0200 (Fr, 09 Apr 2010) | 2 lines
  
  Silence gcc warnings when using UnaryFunction with reference parameters.
........
  r61185 | jhunold | 2010-04-10 19:50:26 +0200 (Sa, 10 Apr 2010) | 2 lines
  
  Dummy-Constructor only for gcc > 4.
........


[SVN r61205]
2010-04-11 15:52:27 +00:00
3f1842a89e Dummy-Constructor only for gcc > 4.
[SVN r61185]
2010-04-10 17:50:26 +00:00
0eac9e329b Silence gcc warnings when using UnaryFunction with reference parameters.
[SVN r61152]
2010-04-09 09:04:51 +00:00
1f226e2dc9 Fixes #3980.
[SVN r60151]
2010-03-04 18:03:05 +00:00
e8bd11887b Fixes #3980.
[SVN r60150]
2010-03-04 18:01:36 +00:00
c12ec71acb rm cmake from trunk. I'm not entirely sure this is necessary to satisfy the inspect script, but I'm not taking any chances, and it is easy to put back
[SVN r56942]
2009-10-17 02:07:38 +00:00
08250885bf rm cmake from the release branch before it goes out broken. Policy dictates that you never commit to release, you commit to trunk and merge to release.
[SVN r56941]
2009-10-17 01:10:45 +00:00
199cb1692b Fixed more links to property_map.
Merged revisions 53478 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r53478 | jewillco | 2009-05-31 02:48:28 +0100 (Sun, 31 May 2009) | 1 line
  
  Fixed more links to property_map
........


[SVN r56569]
2009-10-04 10:31:47 +00:00
2d21b2041f Add boost license info to documentation for a few libraries.
Merged revisions 55098 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r55098 | danieljames | 2009-07-22 23:35:08 +0100 (Wed, 22 Jul 2009) | 8 lines
  
  Add boost license info to documentation for a few libraries.
  
    * Boost.Any: Kevlin Henney is in blanket-permission.txt
    * Boost.Variant: Eric Friedman and Itay Maman are both in blanket-permissions.txt
    * Boost.Concept: Idiana University, University of Notre Dame du Lac, Jeremy Siek,
      Lie-Quan Lee, Andrew Lumsdaine are all listed under blanket permissions.
  
    SGI and HP aren't so their license is left alone.
........


[SVN r55188]
2009-07-26 20:11:03 +00:00
d9282dbe8c Copyrights on CMakeLists.txt to keep them from clogging up the inspect
reports.  This is essentially the same commit as r55095 on the release
branch.



[SVN r55159]
2009-07-26 00:49:56 +00:00
9ceeae9e9f Add boost license info to documentation for a few libraries.
* Boost.Any: Kevlin Henney is in blanket-permission.txt
  * Boost.Variant: Eric Friedman and Itay Maman are both in blanket-permissions.txt
  * Boost.Concept: Idiana University, University of Notre Dame du Lac, Jeremy Siek,
    Lie-Quan Lee, Andrew Lumsdaine are all listed under blanket permissions.

  SGI and HP aren't so their license is left alone.

[SVN r55098]
2009-07-22 22:35:08 +00:00
533211c4ad Add basic copyright/license to keep cmake out of the inspection report
[SVN r55095]
2009-07-22 21:51:01 +00:00
e234ae22f6 concept:: => concepts:: fixes #865
[SVN r53751]
2009-06-08 14:41:16 +00:00
deea7c6a58 Fixed more links to property_map
[SVN r53478]
2009-05-31 01:48:28 +00:00
8842c10761 Merge misc. changes from trunk, mostly minor documentation fixes.
Merged revisions 48412,50921,51042,51369,51386-51387,51506-51507,51668,51802,51804,51881 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r48412 | danieljames | 2008-08-28 11:23:33 +0100 (Thu, 28 Aug 2008) | 1 line
  
  Fix a typo. Thanks to Jon Biggar.
........
  r50921 | danieljames | 2009-01-31 09:36:38 +0000 (Sat, 31 Jan 2009) | 1 line
  
  Remove executable flag from preprocess.cmd. It was a mistake to add it.
........
  r51042 | danieljames | 2009-02-06 00:04:44 +0000 (Fri, 06 Feb 2009) | 1 line
  
  Ignore some version control files in inspect.
........
  r51369 | danieljames | 2009-02-21 18:49:48 +0000 (Sat, 21 Feb 2009) | 1 line
  
  Minor markup fix in concept check documentation.
........
  r51386 | danieljames | 2009-02-22 11:53:28 +0000 (Sun, 22 Feb 2009) | 1 line
  
  Add index.html file for compose, as our server setup doesn't support index.htm files.
........
  r51387 | danieljames | 2009-02-22 11:53:48 +0000 (Sun, 22 Feb 2009) | 5 lines
  
  Add missing index.html file for MPI and GIL.
  
  All the top level libraries now have index.html files but
  several sub-libraries don't. I'm not sure it's worth adding them as many
  of them don't have appropriate subdirectories anyway.
........
  r51506 | danieljames | 2009-03-01 14:16:00 +0000 (Sun, 01 Mar 2009) | 1 line
  
  Update links to command line invocation.
........
  r51507 | danieljames | 2009-03-01 14:16:24 +0000 (Sun, 01 Mar 2009) | 1 line
  
  Use xpointer attributes in the boost build documentation.
........
  r51668 | danieljames | 2009-03-09 20:56:51 +0000 (Mon, 09 Mar 2009) | 1 line
  
  Redirect to the Trac wiki instead of the old one.
........
  r51802 | danieljames | 2009-03-16 20:21:05 +0000 (Mon, 16 Mar 2009) | 1 line
  
  Use paragraphs inside purpose tags.
........
  r51804 | danieljames | 2009-03-16 20:21:46 +0000 (Mon, 16 Mar 2009) | 1 line
  
  Give the variablelist a margin.
........
  r51881 | danieljames | 2009-03-21 15:35:35 +0000 (Sat, 21 Mar 2009) | 1 line
  
  Fix html.
........


[SVN r51897]
2009-03-22 10:42:48 +00:00
2c2d720874 Merge PDF build changes from Trunk.
[SVN r51417]
2009-02-23 18:39:32 +00:00
dc164705ad Minor markup fix in concept check documentation.
[SVN r51369]
2009-02-21 18:49:48 +00:00
a37267f181 Add PDF generation options to fix external links to point to the web site.
Added a few more Boostbook based libs that were missed first time around.
Fixed PDF naming issues.

[SVN r51284]
2009-02-17 10:05:58 +00:00
2fbf9d1375 merge of cmake build files from trunk per beman
[SVN r50756]
2009-01-24 18:57:20 +00:00
3dcaf09ecf merged warning fixes from trunk (-r41358:49813)
[SVN r49814]
2008-11-17 09:57:04 +00:00
30dc63f52f Updating CMake files to latest trunk. Added dependency information for regression tests and a few new macros for internal use.
[SVN r49627]
2008-11-07 17:02:56 +00:00
80de3d1903 Continuing merge of CMake build system files into trunk with the encouragement of Doug Gregor
[SVN r49510]
2008-11-01 13:15:41 +00:00
eb4c1f2587 silence MSVC8 warnings through pragmas, fixes #2296
[SVN r48821]
2008-09-17 18:44:34 +00:00
63c674c575 Improve visibility of concept failure messages
[SVN r47797]
2008-07-25 09:38:53 +00:00
5c06a2ea0b No compilers without partial specialization see this file.
[SVN r47794]
2008-07-25 09:26:15 +00:00
b3fc10803f Improve visibility of concept failure messages
[SVN r47793]
2008-07-25 09:11:23 +00:00
cc5dcdfb33 Worked around an unused variable compiler warning displayed in concept_check.hpp when _ITERATOR_ is not defined.
[SVN r45671]
2008-05-23 08:59:49 +00:00
b15e7d804b Merge changeset 43861, fixing #1716
[SVN r43870]
2008-03-26 16:59:45 +00:00
e7fbe05ee2 Work around intel-10.0-win compiler bug
[SVN r43861]
2008-03-25 20:47:38 +00:00
29f82069d9 Merged revisions 43206,43208-43213 via svnmerge from
https://svn.boost.org/svn/boost/trunk

........
  r43206 | danieljames | 2008-02-10 09:55:03 +0000 (Sun, 10 Feb 2008) | 1 line
  
  Fix some broken links.
........
  r43209 | danieljames | 2008-02-10 14:56:22 +0000 (Sun, 10 Feb 2008) | 1 line
  
  Link to people pages on the website, as they've been removed from the download.
........
  r43210 | danieljames | 2008-02-10 15:02:17 +0000 (Sun, 10 Feb 2008) | 1 line
  
  Point links to the pages that used to be in 'more' to the site.
........
  r43212 | danieljames | 2008-02-10 16:10:16 +0000 (Sun, 10 Feb 2008) | 1 line
  
  Fix links on the home page as well.
........
  r43213 | danieljames | 2008-02-10 16:21:22 +0000 (Sun, 10 Feb 2008) | 1 line
  
  Generated documentation which is no longer generated.
........


[SVN r43214]
2008-02-10 16:39:38 +00:00
a61d139751 Point links to the pages that used to be in 'more' to the site.
[SVN r43210]
2008-02-10 15:02:17 +00:00
2364f0f02a Link to people pages on the website, as they've been removed from the download.
[SVN r43209]
2008-02-10 14:56:22 +00:00
624e9d53c2 Treated Rogue Wave library concept check failure on Tru64/CXX.
[SVN r41955]
2007-12-10 13:40:56 +00:00
997b34b581 Full merge from trunk at revision 41356 of entire boost-root tree.
[SVN r41370]
2007-11-25 18:38:02 +00:00
92ae569516 Full merge from trunk at revision 41356 of entire boost-root tree.
[SVN r41369]
2007-11-25 18:07:19 +00:00
d9ae976994 Moved boost/concept/where.hpp to boost/concept/requires.hpp
Updated reference.htm to include BOOST_CONCEPT_REQUIRES

Fixed a copyright notice.


[SVN r40770]
2007-11-05 04:43:31 +00:00
7dd50ca8f2 Updated Concept Check library documentation.
Changed BOOST_CONCEPT_WHERE to BOOST_CONCEPT_REQUIRES to be more
consistent with the current C++0x proposal, which now uses a
"requires" keyword in lieu of "where."

Factored GCC workarounds into the BOOST_CONCEPT_USAGE macro.


[SVN r40769]
2007-11-05 03:54:19 +00:00
96d6053a52 Starting point for releases
[SVN r39706]
2007-10-05 14:25:06 +00:00
6ed3c013bb Second attempt at fixing usage of 64-bit integer type
[SVN r39363]
2007-09-18 12:09:53 +00:00
2134db9324 Support Win64
[SVN r39353]
2007-09-17 18:33:20 +00:00
9ef681483e Work around bugs in Sun Studio 11
[SVN r39243]
2007-09-13 18:50:50 +00:00
6f04bb5004 Remove V1 Jamfiles
[SVN r38516]
2007-08-08 19:02:26 +00:00
fe5e093f53 This commit was manufactured by cvs2svn to create tag
'Version_1_34_1'.

[SVN r38286]
2007-07-24 19:28:14 +00:00
d0c4fe7914 Patches from Trac #583.
[SVN r37846]
2007-06-01 16:12:08 +00:00
bee3ccbb6c Change tests to run and compile-fail.
[SVN r36196]
2006-11-28 17:28:34 +00:00
cf9b413943 Merged copyright and license addition
[SVN r35907]
2006-11-07 19:27:00 +00:00
c1709f6794 Add copyright, license
[SVN r35905]
2006-11-07 19:11:57 +00:00
a88c1d6a69 Remove obsolete Boost.Build v1 files.
[SVN r35880]
2006-11-06 17:10:46 +00:00
ac6415fac2 Added BOOST_CONCEPT_USAGE for defining usage requirements: Using this
macro is better than simply defining a destructor because usage
patterns will be tested whenever associated types are accessed.


[SVN r35198]
2006-09-19 13:37:20 +00:00
949c2b1b28 Add missing license/copyright
[SVN r35070]
2006-09-11 22:27:29 +00:00
6b4d01994b add missing license/copyright info
[SVN r35068]
2006-09-11 22:08:18 +00:00
b11b270a56 Deal with GCC problems in updated concepts library
[SVN r34418]
2006-06-27 15:01:14 +00:00
178e7549ce Work around GCC 3.3 bug
[SVN r34134]
2006-06-02 15:01:19 +00:00
fb99b2546a Minor cleanups
[SVN r33967]
2006-05-15 13:29:23 +00:00
b087894c08 vc-7.1 workarounds
[SVN r33961]
2006-05-08 00:54:00 +00:00
14450b3d5d Added missing paren
[SVN r33897]
2006-05-01 20:06:13 +00:00
4e524d6c6a Workaround for GCC-2.96
[SVN r33896]
2006-05-01 19:52:34 +00:00
ba2a75c1f9 Added legibility.
[SVN r33895]
2006-05-01 19:45:04 +00:00
79017f985a Killed off "Concept" suffixes on Boost concepts. Maintained
back-compatibility by using a macro to define XxxxConcept when
defining Xxxxx.


[SVN r33894]
2006-05-01 19:40:32 +00:00
f00741c14f Moved library specifics out of boost/concept_check and into boost/concept.
Moved implementation details into boost/concept/detail.
Improved error messages by renaming has_constraints not_satisfied.


[SVN r33893]
2006-05-01 18:25:20 +00:00
8c32f7a5e2 Added missing value_type to InputIteratorConcept
Improved idiomatic fake_sort


[SVN r33889]
2006-05-01 13:17:48 +00:00
bfb6428417 Factored out BOOST_CONCEPT_ASSERT into concept_check/assert.hpp
Fixed the implementation for GCC 3.3.x and comeau
Added BOOST_CONCEPT_WHERE, and tests


[SVN r33887]
2006-05-01 12:50:48 +00:00
80cbd76189 Misc cleanups, missing extensions of integral types to (un)signed char
and, where apropriate, the long long types.


[SVN r33877]
2006-04-30 20:54:13 +00:00
3bce136d94 use idiomatic convertibility assertions.
[SVN r33869]
2006-04-30 03:33:33 +00:00
3c2a976d2a Workarounds for a nasty vc-7.1 bug that only shows up in the iterator
library tests.


[SVN r33866]
2006-04-30 03:01:58 +00:00
24326c9df5 Fixes for concept checking; use destructors for checking classes, misc cleanup.
[SVN r33862]
2006-04-29 20:27:14 +00:00
d4ecb93adb Rework concept checking to look lots more like ConceptGCC.
[SVN r33775]
2006-04-24 04:10:22 +00:00
3e56a7c4ec This commit was manufactured by cvs2svn to create branch 'RC_1_34_0'.
[SVN r33417]
2006-03-21 02:26:31 +00:00
940df353e8 Added Jamfile.v2
[SVN r32349]
2006-01-18 12:14:03 +00:00
8414234a2a documented the restriction on BOOST_CLASS_REQUIRES
[SVN r30917]
2005-09-12 15:17:27 +00:00
4a7d05206e Fixed missing concept_check test -- Jamfile wasn't subincluded
[SVN r30863]
2005-09-07 21:49:08 +00:00
842160c38c _c -> C
[SVN r30862]
2005-09-07 21:03:46 +00:00
d51a7bf94a fixed typo
[SVN r30860]
2005-09-07 20:56:50 +00:00
6f59ef904b Revert Jeremy Siek's patches for now
[SVN r30299]
2005-07-28 18:22:23 +00:00
3cd0be21a7 fixed archetypes for count, etc.
[SVN r30292]
2005-07-28 16:33:20 +00:00
e63353698b changed std::count test
[SVN r30288]
2005-07-28 15:41:07 +00:00
ce3fb4f640 change to input_iterator_archetype to add a type parameter for the
base class of the reference type. Needed this, for example, to get
the concept covering test for std::count right.


[SVN r30287]
2005-07-28 15:39:59 +00:00
166e3207b7 Turn off NDEBUG if it is defined
[SVN r28554]
2005-05-01 14:30:28 +00:00
87f5b1ab63 Minor fixes
[SVN r26024]
2004-10-31 19:55:15 +00:00
9ef32e2e8d c++boost.gif -> boost.png replacement
[SVN r25573]
2004-10-05 15:45:52 +00:00
1ff77e789e Added new types boost::long_long_type and boost::ulong_long_type in boost/config.hpp and applied these types in place of "long long" throughout. As a result, almost all of boost now compiles cleanly with -ansi -pedantic with gcc. Changes tested with gcc 3.3, 2.95, VC7.1 and Intel 8.
[SVN r24899]
2004-09-04 10:34:49 +00:00
bc8f520895 Converted to Boost Software License, Version 1.0
[SVN r24055]
2004-07-26 00:32:12 +00:00
daad09ad49 Fix a typo
[SVN r23353]
2004-07-05 22:58:40 +00:00
ad5f1d47d8 move BOOST_USING_STD_MIN and _MAX and BOOST_PREVENT_MACRO_SUBSTITUTION to the config headers, remove boost/minmax.hpp, update coding guidelines
[SVN r23313]
2004-07-02 01:21:32 +00:00
1731989798 removed trivial iterator
[SVN r23232]
2004-06-28 13:26:29 +00:00
a29797eadc removed mention of Trivial Iterator
[SVN r23231]
2004-06-28 13:26:05 +00:00
9678d4a3f2 remove std_min and std_max, update minmax coding guidelines
[SVN r23162]
2004-06-23 04:49:48 +00:00
1b8f363e90 remove minmax hack from win32.hpp and fix all places that could be affected by the minmax macros
[SVN r22394]
2004-02-26 18:27:02 +00:00
061ed8019a change to conversion operator of input_iterator_archetype::proxy so
as to not use the copy constructor of the value_type


[SVN r22184]
2004-02-06 05:49:31 +00:00
cc25398b06 updating with respect to change in input_iterator_archetype
[SVN r22183]
2004-02-06 05:47:22 +00:00
6547eb9803 fixed broken URLs
[SVN r22037]
2004-01-29 00:45:00 +00:00
8a403e7859 added const to the conversion operator of input_iterator_archetype
[SVN r21866]
2004-01-21 19:03:32 +00:00
ab0a5086b5 Better Borland workaround
[SVN r21848]
2004-01-21 00:34:27 +00:00
308df430d2 borland workaround
[SVN r21800]
2004-01-18 16:21:05 +00:00
7f5d7a5c54 removed default constructor from input iterator archetypes
[SVN r21784]
2004-01-16 18:40:19 +00:00
b4d624d61f added the no_proxy version of input_iterator
[SVN r21684]
2004-01-13 18:05:44 +00:00
a50c9fca5c added input_output_iterator_archetype
[SVN r21578]
2004-01-10 19:49:32 +00:00
669e6938cc Added Caramel/BoostBook concept documentation (finally)
[SVN r21176]
2003-12-08 01:15:31 +00:00
5741cdc2dc Stop using keywords reserved to the implementation
[SVN r20907]
2003-11-22 04:51:00 +00:00
0ecc9d31b5 removed use of trivial iterator
[SVN r20490]
2003-10-25 01:48:54 +00:00
60e6cc268c removed trivial iterator archetype
[SVN r20489]
2003-10-25 01:48:15 +00:00
47ae00bff5 removed TrivialIterator concept
[SVN r20488]
2003-10-25 01:47:53 +00:00
f2abb5931b Use the import rule
[SVN r19968]
2003-09-08 17:38:49 +00:00
358b14915b Fixed forward_iterator_archetype pointer type to be ptr to const.
[SVN r18315]
2003-04-25 21:55:33 +00:00
ce92fda5ba Add missing #include
[SVN r18260]
2003-04-16 14:28:32 +00:00
538b271d24 Small changes to support new iterator adaptors in sandbox
[SVN r18212]
2003-04-09 11:57:59 +00:00
76 changed files with 6126 additions and 3852 deletions

125
.appveyor.yml Normal file
View File

@ -0,0 +1,125 @@
# Copyright 2016, 2017 Peter Dimov
# Copyright 2017 - 2019 James E. King III
# Copyright 2019 - 2021 Alexander Grund
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
#
# Generic Appveyor build script for boostorg repositories
# See: https://github.com/boostorg/boost-ci/
#
# Instructions for customizing this script for your library:
#
# 1. Customize the compilers and language levels you want.
# 2. If you have more than include/, src/, test/, example/, examples/,
# benchmark/ or tools/ directories, set the environment variable DEPINST.
# For example if your build uses code in "bench/" and "fog/" directories:
# - DEPINST: --include bench --include fog
# 3. Enable pull request builds in your boostorg/<library> account.
#
# That's it - the script will do everything else for you.
#
version: 1.0.{build}-{branch}
shallow_clone: true
branches:
only:
- master
- develop
- /bugfix\/.*/
- /feature\/.*/
- /fix\/.*/
- /pr\/.*/
matrix:
fast_finish: false
# Adding MAYFAIL to any matrix job allows it to fail but the build stays green:
allow_failures:
- MAYFAIL: true
environment:
global:
B2_CI_VERSION: 1
GIT_FETCH_JOBS: 4
# see: http://www.boost.org/build/doc/html/bbv2/overview/invocation.html#bbv2.overview.invocation.properties
# to use the default for a given environment, comment it out; recommend you build debug and release however:
# on Windows it is important to exercise all the possibilities, especially shared vs static, however most
# libraries that care about this exercise it in their Jamfiles...
B2_ADDRESS_MODEL: 32,64
B2_LINK: shared,static
# B2_THREADING: threading=multi,single
B2_VARIANT: release
matrix:
- FLAVOR: Visual Studio 2017 C++2a Strict
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
B2_CXXFLAGS: -permissive-
B2_CXXSTD: 2a
B2_TOOLSET: msvc-14.1
- FLAVOR: Visual Studio 2017 C++14/17
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
B2_CXXSTD: 14,17
B2_TOOLSET: msvc-14.1
- FLAVOR: clang-cl
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
B2_ADDRESS_MODEL: 64
B2_CXXSTD: 11,14,17
B2_TOOLSET: clang-win
- FLAVOR: Visual Studio 2015, 2013
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
B2_TOOLSET: msvc-12.0,msvc-14.0
- FLAVOR: Visual Studio 2008, 2010, 2012
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
B2_TOOLSET: msvc-9.0,msvc-10.0,msvc-11.0
B2_ADDRESS_MODEL: 32 # No 64bit support
- FLAVOR: cygwin (32-bit)
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
ADDPATH: C:\cygwin\bin;
B2_ADDRESS_MODEL: 32
B2_CXXSTD: 03,11,14,1z
B2_TOOLSET: gcc
- FLAVOR: cygwin (64-bit)
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
ADDPATH: C:\cygwin64\bin;
B2_ADDRESS_MODEL: 64
B2_CXXSTD: 03,11,14,1z
B2_TOOLSET: gcc
- FLAVOR: mingw32
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
B2_ADDRESS_MODEL: 32
ADDPATH: C:\mingw\bin;
B2_CXXSTD: 03,11,14,1z
B2_TOOLSET: gcc
- FLAVOR: mingw64
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;
B2_ADDRESS_MODEL: 64
B2_CXXSTD: 03,11,14,17,2a
B2_TOOLSET: gcc
install:
- git clone --depth 1 https://github.com/boostorg/boost-ci.git C:\boost-ci-cloned
# Copy ci folder if not testing Boost.CI
- if NOT "%APPVEYOR_PROJECT_NAME%" == "boost-ci" xcopy /s /e /q /i /y C:\boost-ci-cloned\ci .\ci
- rmdir /s /q C:\boost-ci-cloned
- ci\appveyor\install.bat
build: off
test_script: ci\build.bat
for:
# CodeCov coverage build
- matrix:
only: [COVERAGE: true]
test_script: [ps: ci\codecov.ps1]

31
.codecov.yml Normal file
View File

@ -0,0 +1,31 @@
# Copyright 2019 - 2021 Alexander Grund
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
#
# Sample codecov configuration file. Edit as required
codecov:
max_report_age: off
require_ci_to_pass: yes
notify:
# Increase this if you have multiple coverage collection jobs
after_n_builds: 2
wait_for_ci: yes
parsers:
gcov:
branch_detection:
conditional: yes
loop: yes
method: no
macro: no
# Change how pull request comments look
comment:
layout: "reach,diff,flags,files,footer"
# Ignore specific files or folders. Glob patterns are supported.
# See https://docs.codecov.com/docs/ignoring-paths
ignore:
- libs/concept_check/test/
- test/

336
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,336 @@
# Copyright 2020-2021 Peter Dimov
# Copyright 2021 Andrey Semashev
# Copyright 2021 Alexander Grund
# Copyright 2022 James E. King III
#
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
---
name: CI
on:
pull_request:
push:
branches:
- master
- develop
- bugfix/**
- feature/**
- fix/**
- pr/**
concurrency:
group: ${{format('{0}:{1}', github.repository, github.ref)}}
cancel-in-progress: true
env:
ASAN_OPTIONS: allocator_may_return_null=1
GIT_FETCH_JOBS: 8
NET_RETRY_COUNT: 5
B2_CI_VERSION: 1
B2_VARIANT: debug,release
B2_LINK: shared,static
LCOV_BRANCH_COVERAGE: 0
CODECOV_NAME: Github Actions
jobs:
posix:
defaults:
run:
shell: bash
strategy:
fail-fast: false
matrix:
include:
# Linux, gcc
- { compiler: gcc-4.4, cxxstd: '98,0x', os: ubuntu-20.04, container: 'ubuntu:16.04' }
- { compiler: gcc-4.6, cxxstd: '03,0x', os: ubuntu-20.04, container: 'ubuntu:16.04' }
- { compiler: gcc-4.7, cxxstd: '03,11', os: ubuntu-20.04, container: 'ubuntu:16.04' }
- { compiler: gcc-4.8, cxxstd: '03,11', os: ubuntu-18.04 }
- { compiler: gcc-4.9, cxxstd: '03,11', os: ubuntu-20.04, container: 'ubuntu:16.04' }
- { compiler: gcc-5, cxxstd: '03,11,14,1z', os: ubuntu-18.04 }
- { compiler: gcc-6, cxxstd: '03,11,14,17', os: ubuntu-18.04 }
- { compiler: gcc-7, cxxstd: '03,11,14,17', os: ubuntu-18.04 }
- { compiler: gcc-8, cxxstd: '03,11,14,17,2a', os: ubuntu-18.04 }
- { compiler: gcc-9, cxxstd: '03,11,14,17,2a', os: ubuntu-18.04 }
- { compiler: gcc-10, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 }
- { compiler: gcc-11, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 }
- { name: GCC w/ sanitizers, sanitize: yes,
compiler: gcc-11, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 }
- { name: Collect coverage, coverage: yes,
compiler: gcc-10, cxxstd: '03,11', os: ubuntu-20.04, install: 'g++-10-multilib', address-model: '32,64' }
# Linux, clang
- { compiler: clang-3.5, cxxstd: '03,11', os: ubuntu-20.04, container: 'ubuntu:16.04' }
- { compiler: clang-3.6, cxxstd: '03,11,14', os: ubuntu-20.04, container: 'ubuntu:16.04' }
- { compiler: clang-3.7, cxxstd: '03,11,14', os: ubuntu-20.04, container: 'ubuntu:16.04' }
- { compiler: clang-3.8, cxxstd: '03,11,14', os: ubuntu-20.04, container: 'ubuntu:16.04' }
- { compiler: clang-3.9, cxxstd: '03,11,14', os: ubuntu-18.04 }
- { compiler: clang-4.0, cxxstd: '03,11,14', os: ubuntu-18.04 }
- { compiler: clang-5.0, cxxstd: '03,11,14,1z', os: ubuntu-18.04 }
- { compiler: clang-6.0, cxxstd: '03,11,14,17', os: ubuntu-18.04 }
- { compiler: clang-7, cxxstd: '03,11,14,17', os: ubuntu-18.04 }
# Note: clang-8 does not fully support C++20, so it is not compatible with some libstdc++ versions in this mode
- { compiler: clang-8, cxxstd: '03,11,14,17,2a', os: ubuntu-18.04, install: 'clang-8 g++-7', gcc_toolchain: 7 }
- { compiler: clang-9, cxxstd: '03,11,14,17,2a', os: ubuntu-20.04 }
- { compiler: clang-10, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 }
- { compiler: clang-11, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 }
- { name: Clang w/ valgrind, valgrind: yes,
compiler: clang-12, cxxstd: '03,11,14,17,20', os: ubuntu-20.04, install: 'valgrind' }
# libc++
- { compiler: clang-6.0, cxxstd: '03,11,14', os: ubuntu-18.04, stdlib: libc++, install: 'clang-6.0 libc++-dev libc++abi-dev' }
- { compiler: clang-12, cxxstd: '03,11,14,17,20', os: ubuntu-20.04, stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev' }
- { name: Clang w/ sanitizers, sanitize: yes,
compiler: clang-12, cxxstd: '03,11,14,17,20', os: ubuntu-20.04, stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev' }
# OSX, clang
- { compiler: clang, cxxstd: '03,11,14,17,2a', os: macos-10.15, sanitize: yes }
# Coverity Scan
# requires two github secrets in repo to activate; see ci/github/coverity.sh
# does not run on pull requests, only on pushes into develop and master
- { name: Coverity, coverity: yes,
compiler: clang-10, cxxstd: '17', os: ubuntu-20.04, ccache: no }
# multiarch (bigendian testing) - does not support coverage yet
- { name: Big-endian, multiarch: yes,
compiler: clang, cxxstd: '17', os: ubuntu-20.04, ccache: no, distro: fedora, edition: 34, arch: s390x }
timeout-minutes: 120
runs-on: ${{matrix.os}}
container: ${{matrix.container}}
env: {B2_USE_CCACHE: 1}
steps:
- name: Setup environment
run: |
if [ -f "/etc/debian_version" ]; then
echo "DEBIAN_FRONTEND=noninteractive" >> $GITHUB_ENV
export DEBIAN_FRONTEND=noninteractive
fi
if [ -n "${{matrix.container}}" ] && [ -f "/etc/debian_version" ]; then
apt-get -o Acquire::Retries=$NET_RETRY_COUNT update
apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y sudo software-properties-common
# Need (newer) git
for i in {1..${NET_RETRY_COUNT:-3}}; do sudo -E add-apt-repository -y ppa:git-core/ppa && break || sleep 10; done
apt-get -o Acquire::Retries=$NET_RETRY_COUNT update
apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y g++ python libpython-dev git
fi
# multiple job types are not compatible with ccache, they use "ccache: no" in the matrix
if [[ "${{ matrix.ccache }}" == "no" ]]; then
echo "B2_USE_CCACHE=0" >> $GITHUB_ENV
fi
if [[ "${{ matrix.valgrind }}" == "yes" ]]; then
echo "B2_DEFINES=BOOST_NO_STRESS_TEST=1" >> $GITHUB_ENV
echo "B2_TESTFLAGS=testing.launcher=valgrind" >> $GITHUB_ENV
echo "B2_FLAGS=define=BOOST_USE_VALGRIND=1" >> $GITHUB_ENV
echo "VALGRIND_OPTS=--error-exitcode=1" >> $GITHUB_ENV
fi
git config --global pack.threads 0
- uses: actions/checkout@v2
with:
# For coverage builds fetch the whole history, else only 1 commit using a 'fake ternary'
fetch-depth: ${{ matrix.coverage && '0' || '1' }}
- name: Cache ccache
uses: actions/cache@v2
if: env.B2_USE_CCACHE
with:
path: ~/.ccache
key: ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}}
- name: Fetch Boost.CI
uses: actions/checkout@v2
with:
repository: boostorg/boost-ci
ref: master
path: boost-ci-cloned
- name: Get CI scripts folder
run: |
# Copy ci folder if not testing Boost.CI
[[ "$GITHUB_REPOSITORY" =~ "boost-ci" ]] || cp -r boost-ci-cloned/ci .
rm -rf boost-ci-cloned
- name: Install packages
if: startsWith(matrix.os, 'ubuntu')
run: |
SOURCE_KEYS=(${{join(matrix.source_keys, ' ')}})
SOURCES=(${{join(matrix.sources, ' ')}})
# Add this by default
SOURCES+=(ppa:ubuntu-toolchain-r/test)
for key in "${SOURCE_KEYS[@]}"; do
for i in {1..$NET_RETRY_COUNT}; do
wget -O - "$key" | sudo apt-key add - && break || sleep 10
done
done
for source in "${SOURCES[@]}"; do
for i in {1..$NET_RETRY_COUNT}; do
sudo add-apt-repository $source && break || sleep 10
done
done
sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT update
if [[ -z "${{matrix.install}}" ]]; then
pkgs="${{matrix.compiler}}"
pkgs="${pkgs/gcc-/g++-}"
else
pkgs="${{matrix.install}}"
fi
sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y $pkgs
- name: Setup GCC Toolchain
if: matrix.gcc_toolchain
run: |
GCC_TOOLCHAIN_ROOT="$HOME/gcc-toolchain"
echo "GCC_TOOLCHAIN_ROOT=$GCC_TOOLCHAIN_ROOT" >> $GITHUB_ENV
MULTIARCH_TRIPLET="$(dpkg-architecture -qDEB_HOST_MULTIARCH)"
mkdir -p "$GCC_TOOLCHAIN_ROOT"
ln -s /usr/include "$GCC_TOOLCHAIN_ROOT/include"
ln -s /usr/bin "$GCC_TOOLCHAIN_ROOT/bin"
mkdir -p "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET"
ln -s "/usr/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}" "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}"
- name: Setup multiarch
if: matrix.multiarch
run: |
sudo apt-get install --no-install-recommends -y binfmt-support qemu-user-static
sudo docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
git clone https://github.com/jeking3/bdde.git
echo "$(pwd)/bdde/bin/linux" >> ${GITHUB_PATH}
echo "BDDE_DISTRO=${{ matrix.distro }}" >> ${GITHUB_ENV}
echo "BDDE_EDITION=${{ matrix.edition }}" >> ${GITHUB_ENV}
echo "BDDE_ARCH=${{ matrix.arch }}" >> ${GITHUB_ENV}
echo "B2_DEFINES=BOOST_NO_STRESS_TEST=1" >> ${GITHUB_ENV}
echo "B2_WRAPPER=bdde" >> ${GITHUB_ENV}
- name: Setup Boost
env:
B2_ADDRESS_MODEL: ${{matrix.address-model}}
B2_COMPILER: ${{matrix.compiler}}
B2_CXXSTD: ${{matrix.cxxstd}}
B2_SANITIZE: ${{matrix.sanitize}}
B2_STDLIB: ${{matrix.stdlib}}
run: source ci/github/install.sh
- name: Setup coverage collection
if: matrix.coverage
run: ci/github/codecov.sh "setup"
- name: Run tests
if: '!matrix.coverity'
run: ci/build.sh
- name: Upload coverage
if: matrix.coverage
run: ci/codecov.sh "upload"
- name: Run coverity
if: matrix.coverity && github.event_name == 'push' && (github.ref_name == 'develop' || github.ref_name == 'master')
run: ci/github/coverity.sh
env:
COVERITY_SCAN_NOTIFICATION_EMAIL: ${{ secrets.COVERITY_SCAN_NOTIFICATION_EMAIL }}
COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
windows:
defaults:
run:
shell: cmd
strategy:
fail-fast: false
matrix:
include:
- { toolset: msvc-14.2, cxxstd: '14,17,20', addrmd: '32,64', os: windows-2019 }
- { name: Collect coverage, coverage: yes,
toolset: msvc-14.3, cxxstd: '14,17,20', addrmd: '32,64', os: windows-2022 }
- { toolset: gcc, cxxstd: '03,11,14,17,2a', addrmd: '64', os: windows-2019 }
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v2
- name: Fetch Boost.CI
uses: actions/checkout@v2
with:
repository: boostorg/boost-ci
ref: master
path: boost-ci-cloned
- name: Get CI scripts folder
run: |
REM Copy ci folder if not testing Boost.CI
if "%GITHUB_REPOSITORY%" == "%GITHUB_REPOSITORY:boost-ci=%" xcopy /s /e /q /i /y boost-ci-cloned\ci .\ci
rmdir /s /q boost-ci-cloned
- name: Setup Boost
run: ci\github\install.bat
- name: Run tests
if: '!matrix.coverage'
run: ci\build.bat
env:
B2_TOOLSET: ${{matrix.toolset}}
B2_CXXSTD: ${{matrix.cxxstd}}
B2_ADDRESS_MODEL: ${{matrix.addrmd}}
- name: Collect coverage
shell: powershell
if: matrix.coverage
run: ci\opencppcoverage.ps1
env:
B2_TOOLSET: ${{matrix.toolset}}
B2_CXXSTD: ${{matrix.cxxstd}}
B2_ADDRESS_MODEL: ${{matrix.addrmd}}
- name: Upload coverage
if: matrix.coverage
uses: codecov/codecov-action@v2
with:
files: __out/cobertura.xml
CMake:
defaults:
run:
shell: bash
strategy:
fail-fast: false
matrix:
include:
- { os: ubuntu-20.04, build_shared: ON, build_type: Release, generator: 'Unix Makefiles' }
- { os: ubuntu-20.04, build_shared: OFF, build_type: Debug, generator: 'Unix Makefiles' }
- { os: windows-2019, build_shared: ON, build_type: Release, generator: 'Visual Studio 16 2019' }
- { os: windows-2019, build_shared: OFF, build_type: Debug, generator: 'Visual Studio 16 2019' }
timeout-minutes: 120
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v2
- name: Fetch Boost.CI
uses: actions/checkout@v2
with:
repository: boostorg/boost-ci
ref: master
path: boost-ci-cloned
- name: Get CI scripts folder
run: |
# Copy ci folder if not testing Boost.CI
[[ "$GITHUB_REPOSITORY" =~ "boost-ci" ]] || cp -r boost-ci-cloned/ci .
rm -rf boost-ci-cloned
- name: Setup Boost
env: {B2_DONT_BOOTSTRAP: 1}
run: source ci/github/install.sh
- name: Run CMake
run: |
cd "$BOOST_ROOT"
mkdir __build_cmake_test__ && cd __build_cmake_test__
cmake -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DBOOST_INCLUDE_LIBRARIES=$SELF -DBUILD_SHARED_LIBS=${{matrix.build_shared}} -DBUILD_TESTING=ON -DBoost_VERBOSE=ON ..
cmake --build . --config ${{matrix.build_type}}

42
CMakeLists.txt Normal file
View File

@ -0,0 +1,42 @@
# Copyright 2018 Glen Joseph Fernandes
# (glenjofe@gmail.com)
#
# Distributed under the Boost Software License, Version 1.0.
# (http://www.boost.org/LICENSE_1_0.txt)
if(NOT DEFINED IDF_TARGET)
cmake_minimum_required(VERSION 3.5...3.20)
project(boost_concept_check VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
add_library(boost_concept_check INTERFACE)
add_library(Boost::concept_check ALIAS boost_concept_check)
target_include_directories(boost_concept_check INTERFACE include)
target_link_libraries(boost_concept_check INTERFACE
Boost::config
Boost::preprocessor
Boost::static_assert
Boost::type_traits
)
else()
FILE(GLOB_RECURSE headers include/*.h include/*.hpp)
idf_component_register(
SRCS
${headers}
INCLUDE_DIRS
include
REQUIRES
boost_config
boost_preprocessor
boost_static_assert
boost_type_traits
)
endif()

18
Jamfile
View File

@ -1,10 +1,10 @@
subproject libs/concept_check ;
# Boost.ConceptCheck Library Jamfile
#
# Copyright (c) 2018 James E. King III
#
# Use, modification, and distribution are subject to the
# Boost Software License, Version 1.0. (See accompanying file
# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
SEARCH on testing.jam = $(BOOST_BUILD_PATH) ;
include testing.jam ;
compile stl_concept_covering.cpp ;
compile concept_check_test.cpp ;
compile class_concept_check_test.cpp ;
link-fail concept_check_fail_expected.cpp ;
link-fail class_concept_fail_expected.cpp ;
# please order by name to ease maintenance
build-project test ;

23
LICENSE Normal file
View File

@ -0,0 +1,23 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

34
README.md Normal file
View File

@ -0,0 +1,34 @@
ConceptCheck, part of collection of the [Boost C++ Libraries](http://github.com/boostorg),
allows one to add explicit statement and checking of concepts in the style of the proposed C++ language extension.
### License
Distributed under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt).
### Properties
* C++03
* Header-only
### Build Status
Branch | GHA CI | Appveyor | Coverity Scan | codecov.io | Deps | Docs | Tests |
:-------------: | ------ | -------- | ------------- | ---------- | ---- | ---- | ----- |
[`master`](https://github.com/boostorg/concept_check/tree/master) | [![Build Status](https://github.com/boostorg/concept_check/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/boostorg/concept_check/actions?query=branch:master) | [![Build status](https://ci.appveyor.com/api/projects/status/yoj8ae7yopd903i9/branch/master?svg=true)](https://ci.appveyor.com/project/jeking3/concept_check-gp9xw/branch/master) | [![Coverity Scan Build Status](https://scan.coverity.com/projects/16317/badge.svg)](https://scan.coverity.com/projects/boostorg-concept_check) | [![codecov](https://codecov.io/gh/boostorg/concept_check/branch/master/graph/badge.svg)](https://codecov.io/gh/boostorg/concept_check/branch/master)| [![Deps](https://img.shields.io/badge/deps-master-brightgreen.svg)](https://pdimov.github.io/boostdep-report/master/concept_check.html) | [![Documentation](https://img.shields.io/badge/docs-develop-brightgreen.svg)](https://www.boost.org/doc/libs/master/libs/concept_check/doc/html) | [![Enter the Matrix](https://img.shields.io/badge/matrix-master-brightgreen.svg)](http://www.boost.org/development/tests/master/developer/concept_check.html)
[`develop`](https://github.com/boostorg/concept_check/tree/develop) | [![Build Status](https://github.com/boostorg/concept_check/actions/workflows/ci.yml/badge.svg?branch=develop)](https://github.com/boostorg/concept_check/actions?query=branch:develop)| [![Build status](https://ci.appveyor.com/api/projects/status/yoj8ae7yopd903i9/branch/develop?svg=true)](https://ci.appveyor.com/project/jeking3/concept_check-gp9xw/branch/develop) | [![Coverity Scan Build Status](https://scan.coverity.com/projects/16317/badge.svg)](https://scan.coverity.com/projects/boostorg-concept_check) | [![codecov](https://codecov.io/gh/boostorg/concept_check/branch/develop/graph/badge.svg)](https://codecov.io/gh/boostorg/concept_check/branch/develop) | [![Deps](https://img.shields.io/badge/deps-develop-brightgreen.svg)](https://pdimov.github.io/boostdep-report/develop/concept_check.html) | [![Documentation](https://img.shields.io/badge/docs-develop-brightgreen.svg)](https://www.boost.org/doc/libs/develop/libs/concept_check/doc/html) | [![Enter the Matrix](https://img.shields.io/badge/matrix-develop-brightgreen.svg)](http://www.boost.org/development/tests/develop/developer/concept_check.html)
### Directories
| Name | Purpose |
| ----------- | ------------------------------ |
| `doc` | documentation |
| `include` | headers |
| `test` | unit tests |
### More information
* [Ask questions](http://stackoverflow.com/questions/ask?tags=c%2B%2B,boost,boost-concept_check)
* [Report bugs](https://github.com/boostorg/concept_check/issues): Be sure to mention Boost version, platform and compiler you're using. A small compilable code sample to reproduce the problem is always good as well.
* Submit your patches as pull requests against **develop** branch. Note that by submitting patches you agree to license your modifications under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt).
* Discussions about the library are held on the [Boost developers mailing list](http://www.boost.org/community/groups.html#main). Be sure to read the [discussion policy](http://www.boost.org/community/policy.html) before posting and add the `[concept_check]` tag at the beginning of the subject line.

View File

@ -1,14 +1,14 @@
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <vector>
#include <complex>
#include "algorithm"
#include <list>
#include <algorithm>
int main() {
std::list<int> v;
std::stable_sort(v.begin(), v.end());
return 0;
int main()
{
std::vector<std::complex<float> > v;
std_::stable_sort(v.begin(), v.end());
}
// (C) Copyright Jeremy Siek 2000.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

View File

@ -1,20 +1,13 @@
<HTML>
<!--
-- Copyright (c) Jeremy Siek 2000
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. Silicon Graphics makes no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
-->
<!-- Copyright (c) Jeremy Siek 2000 -->
<!-- Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<Head>
<Title>Boost Graph Library: Bibliography</Title>
<Title>Boost Concept Checking Library: Bibliography</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../c++boost.gif"
<IMG SRC="../../boost.png"
ALT="C++ Boost" width="277" height="86">
<BR Clear>
@ -63,7 +56,7 @@ A. A. Stepanov and M. Lee
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A
<A HREF="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</A>(<A
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
</TD></TR></TABLE>

View File

@ -1,70 +0,0 @@
<HTML>
<!--
-- Copyright (c) Jeremy Siek 2000
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. Silicon Graphics makes no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
-->
<Head>
<Title>Boost Graph Library: Bibliography</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<BR Clear>
<H2>Bibliography</H2>
<DL COMMapCT>
<DD><P></P><DT><a name="alexandrescu99:_better_templ_error_messag">1</a>
<DD>Andrei Alexandrescu<BR>
<EM>Better Template Error Messages</EM>.<BR>
C/C++ Users Journal, March, 1999.
<DD><P></P><DT><a name="stroustrup94:_design_evolution">2</a>
<DD>Bjarne Stroustrup<BR>
<EM>Design and Evolution of C++</EM>.<BR>
Addison-Wesley, 1994
<P></P><DT><A NAME="austern99:_gener_progr_stl">3</A>
<DD>
M.&nbsp;H. Austern.
<BR><EM>Generic Programming and the STL</EM>.
<BR>Professional computing series. Addison-Wesley, 1999.
<P></P><DT><A NAME="IB-H965502">4</A>
<DD>
David R. Musser and Atul Saini
<BR><EM>STL Tutorial and Reference Guide</EM>.
<BR>Professional computing series. Addison-Wesley, 1996.
<P></P><DT><A NAME="stepa.lee-1994:the.s:TR">5</A>
<DD>
A. A. Stepanov and M. Lee
<BR><EM>The Standard Template Library</EM>.
<BR>ISO Programming Language C++ Project, May 1994.
<BR>X3J16/94-0095, WG21/N0482
</DL>
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF=http://www.boost.org/people/jeremy_siek.htm>Jeremy Siek</A>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)
</TD></TR></TABLE>
</BODY>
</HTML>

View File

@ -1,35 +0,0 @@
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/concept_check.hpp>
/*
This file verifies that the BOOST_CLASS_REQUIRE macro of the Boost
Concept Checking Library does not cause errors when it is not suppose
to.
*/
struct foo { bool operator()(int) { return true; } };
struct bar { bool operator()(int, char) { return true; } };
class class_requires_test
{
BOOST_CLASS_REQUIRE(int, boost, EqualityComparableConcept);
typedef int* int_ptr; typedef const int* const_int_ptr;
BOOST_CLASS_REQUIRE2(int_ptr, const_int_ptr, boost, EqualOpConcept);
BOOST_CLASS_REQUIRE3(foo, bool, int, boost, UnaryFunctionConcept);
BOOST_CLASS_REQUIRE4(bar, bool, int, char, boost, BinaryFunctionConcept);
};
int
main()
{
class_requires_test x;
boost::ignore_unused_variable_warning(x);
return 0;
}

View File

@ -1,30 +0,0 @@
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/pending/concept_checks.hpp>
/*
This file verifies that class_requires of the Boost Concept Checking
Library catches errors when it is suppose to.
*/
struct foo { };
using namespace boost;
class class_requires_test
{
BOOST_CLASS_REQUIRES(foo, EqualityComparableConcept);
};
int
main()
{
class_requires_test x;
return 0;
}

View File

@ -1,37 +0,0 @@
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/pending/concept_checks.hpp>
/*
This file verifies that the BOOST_CLASS_REQUIRES macro of the Boost
Concept Checking Library does not cause errors when it is not suppose
to.
*/
struct foo { bool operator()(int) { return true; } };
struct bar { bool operator()(int, char) { return true; } };
using namespace boost;
class class_requires_test
{
BOOST_CLASS_REQUIRES(int, EqualityComparableConcept);
typedef int* int_ptr; typedef const int* const_int_ptr;
BOOST_CLASS_REQUIRES2(int_ptr, const_int_ptr, Comparable2Concept);
BOOST_CLASS_REQUIRES3(foo, bool, int, UnaryFunctionConcept);
BOOST_CLASS_REQUIRES4(bar, bool, int, char, BinaryFunctionConcept);
};
int
main()
{
class_requires_test x;
ignore_unused_variable_warning(x);
return 0;
}

View File

@ -1,32 +0,0 @@
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
//
// Change Log:
// 20 Jan 2001 - Added warning suppression (David Abrahams)
#include <boost/concept_check.hpp>
/*
This file verifies that class_requires of the Boost Concept Checking
Library catches errors when it is suppose to.
*/
struct foo { };
class class_requires_test
{
BOOST_CLASS_REQUIRE(foo, boost, EqualityComparableConcept);
};
int
main()
{
class_requires_test x;
(void)x; // suppress unused variable warning
return 0;
}

View File

@ -1,313 +1,330 @@
<HTML>
<!--
-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. We make no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
-->
<Head>
<Title>Concept Check Library</Title>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- Copyright (c) 2000 Jeremy Siek and Andrew Lumsdaine, 2007 David Abrahams -->
<!-- Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<head>
<meta name="generator" content=
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Concept Check Library</title>
<link rel="stylesheet" href="../../rst.css" type="text/css" />
</head>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
"#FF0000">
<img src="../../boost.png" alt="C++ Boost" width="277" height=
"86" /><br clear="none" />
<BR Clear>
<h1>The Boost Concept Check Library (BCCL)</h1>
<H1>The Boost Concept Check Library (BCCL)</H1>
<blockquote>
The Concept Check library allows one to add explicit statement and
checking of <a href=
"http://www.boost.org/more/generic_programming.html#concept">concepts</a> in the style
of the <a href=
"http://www.generic-programming.org/languages/conceptcpp/specification/">proposed
C++ language extension</a>.
</blockquote>
<h2>
<A NAME="sec:concept-checking"></A>
header <a href="../../boost/concept_check.hpp">
<tt>boost/concept_check.hpp</tt></a>
<br>and <a href="../../boost/concept_archetype.hpp">
<tt>boost/concept_archetype.hpp</tt></a>
</h2>
<h2><a name="sec:concept-checking" id="sec:concept-checking"></a>Synopsis</a></h2>
<p>
Generic programming in C++ is characterized by the use of template
parameters to represent abstract data types (or ``concepts'').
However, the C++ language itself does not provide a mechanism for the
writer of a class or function template to explicitly state what
concept the user-supplied template argument should model (or conform
to). The common practice is to name the template parameter after the
required concept as a hint to the user and to state the concept
requirements in the documentation. However, often times the
requirements are vague, incorrect, or nonexistent, which is quite a
problem for the user, since he or she will not know exactly what kind
of input is expected by the template. Furthermore, the following
problems occur:
<p>Generic programming in C++ is characterized by the use of template
parameters to represent abstract data types (or “<a href=
"http://www.boost.org/more/generic_programming.html#concept">concepts</a>”). However, the
C++ language itself does not provide a mechanism for the writer of a class
or function template to explicitly state the concept that the user-supplied
template argument should model (or conform to). Template parameters are
commonly named after the concept they're required to model as a hint to the
user, and to make the concept requirements explicit in code. However, the
compiler doesn't treat these special names specially: a parameter named
<code>RandomAccessIterator</code> is no different to the compiler than one
named <code>T</code>. Furthermore,</p>
<ul>
<li>Compiler error messages resulting from incorrect template
arguments can be particularly difficult to decipher. Often times
the error does not point to the location of the template
call-site, but instead exposes the internals of the template, which
the user should never have to see.</li>
<ul>
<li>Compiler error messages resulting from incorrect template arguments
can be particularly difficult to decipher. Often times the error does not
point to the location of the template call-site, but instead exposes the
internals of the template, which the user should never have to see.</li>
<li>The documented concept requirements may not fully <i>cover</i>
the template, meaning the user could get a compiler error even
though the supplied template arguments meet the documented
requirements.</li>
<li>Without checking from the compiler, the documented requirements are
oftentimes vague, incorrect, or nonexistent, so a user cannot know
exactly what kind of arguments are expected.</li>
<li>The documented concept requirements may be too stringent,
requiring more than is really needed by the template.</li>
<li>The documented concept requirements may not fully <i>cover</i> the
needs of the actual template, meaning the user could get a compiler error
even though the supplied template arguments meet the documented
requirements.</li>
<li>The requirements are not explicitly stated in the code, which
makes the code harder to understand. Also, the code may
get out-of-sync with the documented requirements.</li>
</ul>
<li>The documented concept requirements may be too stringent, requiring
more than is really needed by the template.</li>
The Boost Concept Checking Library provides:
<li>Concept names in code may drift out-of-sync with the documented
requirements.</li>
</ul><p>The Boost Concept Checking Library provides:
<ul>
<li>A mechanism for inserting compile-time checks of template
parameters.</li>
<ul>
<li>A mechanism for inserting compile-time checks on template parameters
at their point of use.</li>
<li>A framework for specifying concept requirements though concept
checking classes.</li>
<li>A framework for specifying concept requirements through concept
checking classes.</li>
<li>A mechanism for verifying that concept requirements cover the template.</li>
<li>A mechanism for verifying that concept requirements cover the
template.</li>
<li>A suite of concept checking classes and archetype classes that
match the concept requirements in the C++ Standard Library.</li>
</ul>
<li>A suite of concept checking classes and archetype classes that match
the concept requirements in the C++ Standard Library.</li>
The mechanisms use standard C++ and introduce no run-time
overhead. The main cost of using the mechanism is in compile-time.
<li>An alternative to the use of traits classes for accessing associated
types that mirrors the syntax proposed for the next C++ standard.</li>
</ul><p>The mechanisms use standard C++ and introduce no run-time overhead.
The main cost of using the mechanism is in compile-time.</p>
<p>
Any programmer writing class or function templates ought to make
concept checking a normal part of their code writing routine. A
concept check should be inserted for each template parameter in a
component's public interface. If the concept is one of the ones from
the Standard Library, then simply use the matching concept checking
class in the BCCL. If not, then write a new concept checking class -
after all, they are typically only a few lines long. For new concepts,
a matching archetype class should also be created, which is a minimal
skeleton-implementation of the concept
<p><strong>Every programmer writing class or function templates ought to
make concept checking a normal part of their code writing routine.</strong>
A concept check should be inserted for each template parameter in a
component's public interface. If the concept is one of the ones from the
Standard Library, then simply use the matching concept checking class in
the BCCL. If not, then write a new concept checking class - after all, they
are typically only a few lines long. For new concepts, a matching archetype
class should also be created, which is a minimal skeleton-implementation of
the concept</p>
<p>
The documentation is organized into the following sections.
<p>The documentation is organized into the following sections.</p>
<OL>
<LI><a href="#introduction">Introduction</a></LI>
<LI><a href="#motivating-example">Motivating Example</a></LI>
<LI><a href="#history">History</a></LI>
<LI><a href="#publications">Publications</a></LI>
<LI><a href="#acknowledgements">Acknowledgements</a></LI>
<LI><a href="./using_concept_check.htm">Using Concept Checks</a></LI>
<LI><a href="creating_concepts.htm">Creating Concept Checking Classes</a></LI>
<LI><a href="./concept_covering.htm">Concept Covering and Archetypes</a></LI>
<LI><a href="./prog_with_concepts.htm" ">Programming With Concepts</a></LI>
<LI><a href="./implementation.htm">Implementation</a></LI>
<LI><a href="./reference.htm">Reference</a></LI>
</OL>
<ol>
<li><a href="#introduction">Introduction</a></li>
<p>
<a href="../../people/jeremy_siek.htm">Jeremy Siek</a> contributed
this library. <a href="../../people/beman_dawes.html">Beman Dawes</a>
managed the formal review.
<li><a href="#motivating-example">Motivating Example</a></li>
<h2><a name="introduction">Introduction</a></h2>
A <i>concept</i> is a set of requirements (valid expressions,
associated types, semantic invariants, complexity guarantees, etc.)
that a type must fulfill to be correctly used as arguments in a call
to a generic algorithm. In C++, concepts are represented by formal
template parameters to function templates (generic algorithms).
However, C++ has no explicit mechanism for representing concepts ---
template parameters are merely placeholders. By convention, these
parameters are given names corresponding to the concept that is
required, but a C++ compiler does not enforce compliance to the
concept when the template parameter is bound to an actual type.
<li><a href="#history">History</a></li>
<p>
Naturally, if a generic algorithm is invoked with a type that does not
fulfill at least the syntactic requirements of the concept, a
compile-time error will occur. However, this error will not <i>per
se</i> reflect the fact that the type did not meet all of the
requirements of the concept. Rather, the error may occur deep inside
the instantiation hierarchy at the point where an expression is not
valid for the type, or where a presumed associated type is not
available. The resulting error messages are largely uninformative and
basically impenetrable.
<li><a href="#publications">Publications</a></li>
<p>
What is required is a mechanism for enforcing ``concept safety'' at
(or close to) the point of instantiation. The Boost Concept Checking
Library uses some standard C++ constructs to enforce early concept
compliance and that provides more informative error messages upon
non-compliance.
<li><a href="#acknowledgements">Acknowledgements</a></li>
<p>
Note that this technique only addresses the syntactic
requirements of concepts (the valid expressions and associated types).
We do not address the semantic invariants or complexity guarantees,
which are also part of concept requirements..
<li><a href="./using_concept_check.htm">Using Concept Checks</a></li>
<h2><a name="motivating-example">Motivating Example</a></h2>
<li><a href="creating_concepts.htm">Creating Concept Checking
Classes</a></li>
We present a simple example to illustrate incorrect usage of a
template library and the resulting error messages. In the code below,
the generic <tt>std::stable_sort()</tt> algorithm from the Standard
Template Library (STL)[<a
href="bibliography.htm#austern99:_gener_progr_stl">3</a>, <a
href="bibliography.htm#IB-H965502">4</a>,<a
href="bibliography.htm#stepa.lee-1994:the.s:TR">5</a>] is applied to
a linked list.
<li><a href="./concept_covering.htm">Concept Covering and
Archetypes</a></li>
<pre>
<li><a href="./prog_with_concepts.htm">Programming With Concepts</a></li>
<li><a href="./implementation.htm">Implementation</a></li>
<li><a href="./reference.htm">Reference</a></li>
</ol>
<p><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a> contributed this
library. <a href="http://www.boost.org/people/beman_dawes.html">Beman Dawes</a> managed
the formal review. <a href="http://www.boost.org/people/dave_abrahams.htm">Dave
Abrahams</a> contributed a rewrite that updated syntax to be more
compatible with proposed syntax for concept support the C++ core
language.</p>
<h2><a name="introduction" id="introduction">Introduction</a></h2><p>A
<i>concept</i> is a set of requirements (valid expressions, associated
types, semantic invariants, complexity guarantees, etc.) that a type must
fulfill to be correctly used as arguments in a call to a generic algorithm.
In C++, concepts are represented by formal template parameters to function
templates (generic algorithms). However, C++ has no explicit mechanism for
representing concepts—template parameters are merely placeholders. By
convention, these parameters are given names corresponding to the concept
that is required, but a C++ compiler does not enforce compliance to the
concept when the template parameter is bound to an actual type.
<p>Naturally, if a generic algorithm is invoked with a type that does not
fulfill at least the syntactic requirements of the concept, a compile-time
error will occur. However, this error will not <i>per se</i> reflect the
fact that the type did not meet all of the requirements of the concept.
Rather, the error may occur deep inside the instantiation hierarchy at the
point where an expression is not valid for the type, or where a presumed
associated type is not available. The resulting error messages are largely
uninformative and basically impenetrable.</p>
<p>What is required is a mechanism for enforcing
“concept safety” at (or close to) the point
of instantiation. The Boost Concept Checking Library uses some standard C++
constructs to enforce early concept compliance and that provides more
informative error messages upon non-compliance.</p>
<p>Note that this technique only addresses the syntactic requirements of
concepts (the valid expressions and associated types). We do not address
the semantic invariants or complexity guarantees, which are also part of
concept requirements..</p>
<h2><a name="motivating-example" id="motivating-example">Motivating
Example</a></h2>
<p>We present a simple example to illustrate incorrect usage of a template
library and the resulting error messages. In the code below, the generic
<tt>std::stable_sort()</tt> algorithm from the Standard Template Library
(STL)[<a href="bibliography.htm#austern99:_gener_progr_stl">3</a>, <a href=
"bibliography.htm#IB-H965502">4</a>,<a href=
"bibliography.htm#stepa.lee-1994:the.s:TR">5</a>] is applied to a linked
list.</p>
<pre>
<a href="./bad_error_eg.cpp">bad_error_eg.cpp</a>:
1 #include &lt;list&gt;
2 #include &lt;algorithm&gt;
3
4 int main(int, char*[]) {
5 std::list&lt;int&gt; v;
6 std::stable_sort(v.begin(), v.end());
7 return 0;
8 }
<font color="gray">1</font> #include &lt;vector&gt;
<font color="gray">2</font color="gray"> #include &lt;complex&gt;
<font color="gray">3</font color="gray"> #include &lt;algorithm&gt;
<font color="gray">4</font color="gray">
<font color="gray">5</font color="gray"> int main()
<font color="gray">6</font color="gray"> {
<font color="gray">7</font color="gray"> std::vector&lt;std::complex&lt;float&gt; &gt; v;
<font color="gray">8</font color="gray"> std::stable_sort(v.begin(), v.end());
<font color="gray">9</font color="gray"> }
</pre>
Here, the
<tt>std::stable_sort()</tt> algorithm is prototyped as follows:
<pre>
<p>Here, the <tt>std::stable_sort()</tt> algorithm is prototyped as
follows:</p>
<pre>
template &lt;class RandomAccessIterator&gt;
void stable_sort(RandomAccessIterator first, RandomAccessIterator last);
</pre>
Attempting to compile this code with Gnu C++ produces the following
compiler error. The output from other compilers is listed in the
Appendix.
<pre>
stl_algo.h: In function `void __merge_sort_loop&lt;_List_iterator
&lt;int,int &amp;,int *&gt;, int *, int&gt;(_List_iterator&lt;int,int &amp;,int *&gt;,
_List_iterator&lt;int,int &amp;,int *&gt;, int *, int)':
stl_algo.h:1448: instantiated from `__merge_sort_with_buffer
&lt;_List_iterator&lt;int,int &amp;,int *&gt;, int *, int&gt;(
_List_iterator&lt;int,int &amp;,int *&gt;, _List_iterator&lt;int,int &amp;,int *&gt;,
int *, int *)'
stl_algo.h:1485: instantiated from `__stable_sort_adaptive&lt;
_List_iterator&lt;int,int &amp;,int *&gt;, int *, int&gt;(_List_iterator
&lt;int,int &amp;,int *&gt;, _List_iterator&lt;int,int &amp;,int *&gt;, int *, int)'
stl_algo.h:1524: instantiated from here
stl_algo.h:1377: no match for `_List_iterator&lt;int,int &amp;,int *&gt; &amp; -
_List_iterator&lt;int,int &amp;,int *&gt; &amp;'
<p>Attempting to compile this code with Gnu C++ produces the following
compiler error:</p>
<pre>
/usr/include/c++/4.1.2/bits/stl_algo.h: In function void std::
__insertion_sort(_RandomAccessIterator, _RandomAccessIterator) [with
_RandomAccessIterator = __gnu_cxx::__normal_iterator&lt;std::complex&lt;float
&gt;*, std::vector&lt;std::complex&lt;float&gt;, std::allocator&lt;std::complex&lt;
float&gt; &gt; &gt; &gt;]:
/usr/include/c++/4.1.2/bits/stl_algo.h:3066: instantiated from void
std::__inplace_stable_sort(_RandomAccessIterator,
_RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::
__normal_iterator&lt;std::complex&lt;float&gt;*, std::vector&lt;std::complex&lt;
float&gt;, std::allocator&lt;std::complex&lt;float&gt; &gt; &gt; &gt;]
/usr/include/c++/4.1.2/bits/stl_algo.h:3776: instantiated from void
std::stable_sort(_RandomAccessIterator, _RandomAccessIterator) [with
_RandomAccessIterator = __gnu_cxx::__normal_iterator&lt;std::complex&lt;float
&gt;*, std::vector&lt;std::complex&lt;float&gt;, std::allocator&lt;std::complex&lt;
float&gt; &gt; &gt; &gt;]
bad_error_eg.cpp:8: instantiated from here
/usr/include/c++/4.1.2/bits/stl_algo.h:2277: error: no match for
operator&lt; in __val &lt; __first. __gnu_cxx::__normal_iterator&lt;
_Iterator, _Container&gt;::operator* [with _Iterator = std::complex&lt;float
&gt;*, _Container = std::vector&lt;std::complex&lt;float&gt;, std::allocator&lt;
std::complex&lt;float&gt; &gt; &gt;]()
</pre>
In this case, the fundamental error is that
<tt>std:list::iterator</tt> does not model the concept of <a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
RandomAccessIterator</a>. The list iterator is only bidirectional, not
fully random access (as would be a vector iterator). Unfortunately,
there is nothing in the error message to indicate this to the user.
<p>In this case, the fundamental error is
that <tt>std:complex&lt;float&gt;</tt> does not model the <a href=
"http://www.boost.org/sgi/stl/LessThanComparable.html">LessThanComparable</a>
concept. Unfortunately, there is nothing in the error message to
indicate that to the user.</p>
<p>
To a C++ programmer having enough experience with template libraries
the error may be obvious. However, for the uninitiated, there are several
reasons why this message would be hard to understand.
<p>The error may be obvious to a C++ programmer having enough
experience with template libraries, but there are several reasons
why this message could be hard for the uninitiated to
understand:</p>
<OL>
<LI> The location of the error, line 6 of <tt>bad_error_eg.cpp</tt>
is not pointed to by the error message, despite the fact that Gnu C++
prints up to 4 levels deep in the instantiation stack.
<LI> There is no textual correlation between the error message and the
documented requirements for <tt>std::stable_sort()</tt> and for
<a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
RandomAccessIterator</a>.
<LI> The error message is overly long, listing functions internal
to the STL that the user does not (and should not!) know or care
about.
<LI> With so many internal library functions listed in the error
message, the programmer could easily infer that the error is due
to the library, rather than to his or her own code.
</OL>
<ol>
<li>There is no textual correlation between the error message and the
documented requirements for <tt>std::stable_sort()</tt> and for <a href=
"http://www.boost.org/sgi/stl/LessThanComparable.html">LessThanComparable</a>.</li>
The following is an example of what we might expect from a more
informative message (and is in fact what the Boost Concept Checking
Library produces):
<li>The error message is overly long, listing functions internal
to the STL (e.g. <code>__insertion_sort</code>) that the user
does not (and should not!) know or care about.</li>
<pre>
boost/concept_check.hpp: In method `void LessThanComparableConcept
&lt;_List_iterator&lt;int,int &amp;,int *&gt; &gt;::constraints()':
boost/concept_check.hpp:334: instantiated from `RandomAccessIteratorConcept
&lt;_List_iterator&lt;int,int &amp;,int *&gt; &gt;::constraints()'
bad_error_eg.cpp:6: instantiated from `stable_sort&lt;_List_iterator
&lt;int,int &amp;,int *&gt; &gt;(_List_iterator&lt;int,int &amp;,int *&gt;,
_List_iterator&lt;int,int &amp;,int *&gt;)'
boost/concept_check.hpp:209: no match for `_List_iterator&lt;int,int &amp;,int *&gt; &amp;
&lt; _List_iterator&lt;int,int &amp;,int *&gt; &amp;'
<li>With so many internal library functions listed in the error message,
the programmer could easily infer that the problem is in the library,
rather than in his or her own code.</li>
</ol>
<p>The following is an example of what we might expect from a more
informative message (and is in fact what the Boost Concept Checking Library
produces):</p>
<pre>
boost/concept_check.hpp: In destructor boost::LessThanComparable&lt;TT&gt;::~
LessThanComparable() [with TT = std::complex&lt;float&gt;]:
boost/concept/detail/general.hpp:29: instantiated from static void boost::
concepts::requirement&lt;Model&gt;::failed() [with Model = boost::
LessThanComparable&lt;std::complex&lt;float&gt; &gt;]
boost/concept/requires.hpp:30: instantiated from boost::_requires_&lt;void
(*)(boost::LessThanComparable&lt;std::complex&lt;float&gt; &gt;)&gt;
bad_error_eg.cpp:8: instantiated from here
boost/concept_check.hpp:236: error: no match for operator&lt; in ((boost::
LessThanComparable&lt;std::complex&lt;float&gt; &gt;*)this)-&gt;boost::
LessThanComparable&lt;std::complex&lt;float&gt; &gt;::a &lt; ((boost::
LessThanComparable&lt;std::complex&lt;float&gt; &gt;*)this)-&gt;boost::
LessThanComparable&lt;std::complex&lt;float&gt; &gt;::b
</pre>
This message rectifies several of the shortcomings of the standard
error messages.
<p>This message rectifies several of the shortcomings of the standard error
messages.</p>
<UL>
<LI> The location of the error, <tt>bad_error_eg.cpp:6</tt> is
specified in the error message.
<LI> The message refers explicitly to concepts that the user can look
up in the STL documentation (<a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
RandomAccessIterator</a>).
<LI> The error message is now much shorter and does not reveal
internal STL functions.
<LI> The presence of <tt>concept_check.hpp</tt> and
<tt>constraints()</tt> in the error message alerts the user to the
fact that the error lies in the user code and not in the library
implementation.
</UL>
<ul>
<li>The message refers explicitly to concepts that the user can look up
in the STL documentation (<a href=
"http://www.boost.org/sgi/stl/LessThanComparable.html">LessThanComparable</a>).</li>
<h2><a name="history">History</a></h2>
<li>The error message is now much shorter and does not reveal
internal STL functions, nor indeed does it even point
to <code>std::stable_sort</code>.</li>
An earlier version of this concept checking system was developed by
the author while working at SGI in their C++ compiler and library
group. The earlier version is now part of the SGI STL distribution. The
boost concept checking library differs from the concept checking in
the SGI STL in that the definition of concept checking classes has
been greatly simplified, at the price of less helpful verbiage in the
error messages.
<li>The presence of <tt>concept_check.hpp</tt> in the error message
alerts the user to the fact that the error lies in the user code and not
in the library implementation.</li>
</ul>
<h2><a name="publications">Publications</a></h2>
<h2><a name="history" id="history">History</a></h2>
<ul>
<li><a href="http://www.oonumerics.org/tmpw00/">
C++ Template Workshop 2000</a>, Concept Checking</li>
</ul>
<p>The first version of this concept checking system was developed
by Jeremy Siek while working at SGI in their C++ compiler and
library group. That version is now part of the SGI STL
distribution. The system originally introduced as the boost concept
checking library differs from concept checking in the SGI STL in
that the definition of concept checking classes was greatly
simplified, at the price of less helpful verbiage in the error
messages. In 2006 the system was rewritten (preserving backward
compatibility) by Dave Abrahams to be easier to use, more similar to
the proposed concept support the C++ core language, and to give
better error messages.
</p>
<h2><a name="acknowledgements">Acknowledgements</a></h2>
<h2><a name="publications" id="publications">Publications</a></h2>
The idea to use function pointers to cause instantiation is due to
Alexander Stepanov. I am not sure of the origin of the idea to use
expressions to do up-front checking of templates, but it did appear in
D&amp;E[
<a href="bibliography.htm#stroustrup94:_design_evolution">2</a>].
Thanks to Matt Austern for his excellent documentation and
organization of the STL concepts, upon which these concept checks
are based. Thanks to Boost members for helpful comments and
reviews.
<ul>
<li><a href="http://www.oonumerics.org/tmpw00/">C++ Template Workshop
2000</a>, Concept Checking</li>
</ul>
<h2><a name="acknowledgements" id=
"acknowledgements">Acknowledgements</a></h2><p>The idea to use function
pointers to cause instantiation is due to Alexander Stepanov. We are not sure
of the origin of the idea to use expressions to do up-front checking of
templates, but it did appear in D&amp;E[ <a href=
"bibliography.htm#stroustrup94:_design_evolution">2</a>]. Thanks to Matt
Austern for his excellent documentation and organization of the STL
concepts, upon which these concept checks are based. Thanks to Boost
members for helpful comments and reviews.
<p>
<a href="./using_concept_check.htm">Next: Using Concept Checks</a>
<p><a href="./using_concept_check.htm">Next: Using Concept
Checks</a><br /></p>
<hr />
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
</TD></TR></TABLE>
<table>
<tr valign="top">
<td nowrap="nowrap">Copyright &copy; 2000</td>
</BODY>
</HTML>
<td><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
"mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>),
2007 <a href="mailto:dave@boost-consulting.com">David Abrahams</a>.
</td>
</tr>
</table>
</body>
</html>

View File

@ -1,23 +0,0 @@
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/concept_check.hpp>
/*
This file verifies that function_requires() of the Boost Concept
Checking Library catches errors when it is suppose to.
*/
struct foo { };
int
main()
{
boost::function_requires< boost::EqualityComparableConcept<foo> >();
return 0;
}

View File

@ -1,999 +0,0 @@
<HTML>
<!--
-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. We make no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
-->
<Head>
<Title>Concept Checking</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<BR Clear>
<H1>
<A NAME="sec:concept-checking"></A>
header <a href="../../boost/pending/concept_checks.hpp">
<tt>boost/concept_checks.hpp</tt></a> and <a href="../../boost/pending/concept_archetypes.hpp">
<tt>boost/concept_archetypes.hpp</tt></a>
</H1>
<p>
Generic programming in C++ is characterized by the use of template
parameters to represent abstract data types (or ``concepts'').
However, the C++ language itself does not provide a mechanism for
explicitly handling concepts. As a result, it can be difficult to
insure that a concrete type meets the requirements of the concept it
is supposed to represent. Error messages resulting from incorrect use
of a concrete type can be particularly difficult to decipher. The
Boost Concept Checking Library provides mechanisms for checking
parameters in C++ template libraries. The mechanisms use standard C++
and introduce no run-time overhead. The main cost of using the
mechanism is in compile-time.
The documentation is organized into the following sections.
<OL>
<LI><a href="#introduction">Introduction</a></LI>
<LI><a href="#motivating-example">Motivating Example</a></LI>
<LI><a href="#using-concept-checks">Using Concept Checks</a></LI>
<LI><a href="#creating-concept-checks">Creating Concept Checking Classes</a></LI>
<LI><a href="#concept-covering">Concept Covering and Archetypes</a></LI>
<LI><a href="#programming-with-concepts">Programming With Concepts</a></LI>
<LI><a href="#implementation">Implementation</a></LI>
<LI><a href="#reference">Reference</a></LI>
<OL>
<LI><a href="#functions">Functions</a></LI>
<LI><a href="#classes">Classes</a></LI>
<LI><a href="#basic-concepts">Basic Concept Checking Classes</a></LI>
<LI><a href="#iterator-concepts">Iterator Concept Checking Classes</a></LI>
<LI><a href="#function-object-concepts">Function Object Concept Checking Classes</a></LI>
<LI><a href="#container-concepts">Container Concept Checking Classes</a></LI>
<LI><a href="#basic-archetype">Basic Archetype Classes</a></LI>
<LI><a href="#iterator-archetype">Iterator Archetype Classes</a></LI>
<LI><a href="#function-object-archetype">Function Object Archetype Classes</a></LI>
<LI><a href="#container-archetype">Container Archetype Classes</a></LI>
</OL>
<LI><a href="#history">History</a></LI>
<LI><a href="#publications">Publications</a></LI>
<LI><a href="#acknowledgements">Acknowledgements</a></LI>
</OL>
<p>
<a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>
contributed this library. X managed the formal review.
<h2><a name="introduction">Introduction</a></h2>
A <i>concept</i> is a set of requirements (valid expressions,
associated types, semantic invariants, complexity guarantees, etc.)
that a type must fulfill to be correctly used as arguments in a call
to a generic algorithm. In C++, concepts are represented by formal
template parameters to function templates (generic algorithms).
However, C++ has no explicit mechanism for representing concepts ---
template parameters are merely placeholders. By convention, these
parameters are given names corresponding to the concept that is
required, but a C++ compiler does not enforce compliance to the
concept when the template parameter is bound to an actual type.
<p>
Naturally, if a generic algorithm is invoked with a type that does not
fulfill at least the syntactic requirements of the concept, a
compile-time error will occur. However, this error will not <i>per
se</i> reflect the fact that the type did not meet all of the
requirements of the concept. Rather, the error may occur deep inside
the instantiation hierarchy at the point where an expression is not
valid for the type, or where a presumed associated type is not
available. The resulting error messages are largely uninformative and
basically impenetrable.
<p>
What is required is a mechanism for enforcing ``concept safety'' at
(or close to) the point of instantiation. The Boost Concept Checking
Library uses some standard C++ constructs to enforce early concept
compliance and that provides more informative error messages upon
non-compliance.
<p>
Note that this technique only addresses the syntactic
requirements of concepts (the valid expressions and associated types).
We do not address the semantic invariants or complexity guarantees,
which are also part of concept requirements..
<h2><a name="motivating-example">Motivating Example</a></h2>
We present a simple example to illustrate incorrect usage of a
template library and the resulting error messages. In the code below,
the generic <tt>std::stable_sort()</tt> algorithm from the Standard
Template Library (STL)[<a
href="bibliography.html#austern99:_gener_progr_stl">3</a>, <a
href="bibliography.html#IB-H965502">4</a>,<a
href="bibliography.html#stepa.lee-1994:the.s:TR">5</a>] is applied to
a linked list.
<pre>
<a href="./bad_error_eg.cpp">bad_error_eg.cpp</a>:
1 #include &lt;list&gt;
2 #include &lt;algorithm&gt;
3
4 struct foo {
5 bool operator&lt;(const foo&) const { return false; }
6 };
7 int main(int, char*[]) {
8 std::list&lt;foo&gt; v;
9 std::stable_sort(v.begin(), v.end());
10 return 0;
11 }
</pre>
Here, the
<tt>std::stable_sort()</tt> algorithm is prototyped as follows:
<pre>
template &lt;class RandomAccessIterator&gt;
void stable_sort(RandomAccessIterator first, RandomAccessIterator last);
</pre>
Attempting to compile this code with Gnu C++ produces the following
compiler error. The output from other compilers is listed in the
Appendix.
<pre>
stl_algo.h: In function `void __merge_sort_loop&lt;_List_iterator
&lt;foo,foo &,foo *&gt;, foo *, int&gt;(_List_iterator&lt;foo,foo &,foo *&gt;,
_List_iterator&lt;foo,foo &,foo *&gt;, foo *, int)':
stl_algo.h:1448: instantiated from `__merge_sort_with_buffer
&lt;_List_iterator&lt;foo,foo &,foo *&gt;, foo *, int&gt;(
_List_iterator&lt;foo,foo &,foo *&gt;, _List_iterator&lt;foo,foo &,foo *&gt;,
foo *, int *)'
stl_algo.h:1485: instantiated from `__stable_sort_adaptive&lt;
_List_iterator&lt;foo,foo &,foo *&gt;, foo *, int&gt;(_List_iterator
&lt;foo,foo &,foo *&gt;, _List_iterator&lt;foo,foo &,foo *&gt;, foo *, int)'
stl_algo.h:1524: instantiated from here
stl_algo.h:1377: no match for `_List_iterator&lt;foo,foo &,foo *&gt; & -
_List_iterator&lt;foo,foo &,foo *&gt; &'
</pre>
In this case, the fundamental error is that
<tt>std:list::iterator</tt> does not model the concept of <a
href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
RandomAccessIterator</a>. The list iterator is only bidirectional, not
fully random access (as would be a vector iterator). Unfortunately,
there is nothing in the error message to indicate this to the user.
<p>
To a C++ programmer having enough experience with template libraries
the error may be obvious. However, for the uninitiated, there are several
reasons why this message would be hard to understand.
<OL>
<LI> The location of the error, line 9 of <tt>bad_error_eg.cpp</tt>
is not pointed to by the error message, despite the fact that Gnu C++
prints up to 4 levels deep in the instantiation stack.
<LI> There is no textual correlation between the error message and the
documented requirements for <tt>std::stable_sort()</tt> and for
<a
href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
RandomAccessIterator</a>.
<LI> The error message is overly long, listing functions internal
to the STL that the user does not (and should not!) know or care
about.
<LI> With so many internal library functions listed in the error
message, the programmer could easily infer that the error is due
to the library, rather than to his or her own code.
</OL>
The following is an example of what we might expect from a more
informative message (and is in fact what the Boost Concept Checking
Library produces):
<pre>
concept_checks.hpp: In method `void LessThanComparable_concept
&lt;_List_iterator&lt;foo,foo &,foo *> >::constraints()':
concept_checks.hpp:334: instantiated from `RandomAccessIterator_concept
&lt;_List_iterator&lt;foo,foo &,foo *> >::constraints()'
bad_error_eg.cpp:9: instantiated from `stable_sort&lt;_List_iterator
&lt;foo,foo &,foo *> >(_List_iterator&lt;foo,foo &,foo *>,
_List_iterator&lt;foo,foo &,foo *>)'
concept_checks.hpp:209: no match for `_List_iterator&lt;foo,foo &,foo *> &
&lt; _List_iterator&lt;foo,foo &,foo *> &'
</pre>
This message rectifies several of the shortcomings of the standard
error messages.
<UL>
<LI> The location of the error, <tt>bad_error_eg.cpp:9</tt> is
specified in the error message.
<LI> The message refers explicitly to concepts that the user can look
up in the STL documentation (<a
href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
RandomAccessIterator</a>).
<LI> The error message is now much shorter and does not reveal
internal STL functions.
<LI> The presence of <tt>concept_checks.hpp</tt> and
<tt>constraints()</tt> in the error message alerts the user to the
fact that the error lies in the user code and not in the library
implementation.
</UL>
<h2><a name="using-concept-checks">Using Concept Checks</a></h2>
For each concept there is a concept checking class which can be used
to make sure that a given type (or set of types) models the concept.
The Boost Concept Checking Library includes concept checking classes
for all of the concepts used in the C++ standard library and a few
more. The <a href="#reference">Reference</a> section below lists these
concept checking classes. In addition, other boost libraries come with
concept checking classes for the concepts that are particular to those
libraries. An example of one of these classes is the
<tt>EqualityComparableConcept</tt> class.
<pre>
template &lt;class T&gt; struct EqualityComparableConcept;
</pre>
Each concept checking class has a member function named
<tt>constraints()</tt> which contains the valid expressions for the
concept. To check whether some type, say <tt>foo</tt>, is
EqualityComparable, we need to instantiate the concept checking class
with foo: <tt>EqualityComparableConcept&lt;foo&gt;</tt> and then find
a way to get the compiler to compile the <tt>constraints()</tt>
function without actually calling it. The Boost Concept Checking
Library defines two utilities that make this easy:
<tt>function_requires()</tt> and <tt>BOOST_CLASS_REQUIRES</tt>.
<tt>function_requires()</tt> function can be used in function bodies
and the <tt>BOOST_CLASS_REQUIRES</tt> macro can be used inside class
bodies. The <tt>function_requires()</tt> function takes no arguments,
but has a template parameter for the concept checking class. This
means that the instantiated concept checking class must be given as an
explicit template argument, as shown below.
<pre>
void some_function_using_foo() {
function_requires&lt; EqualityComparableConcept&lt;foo&gt; &gt;();
// ...
};
</pre>
The <tt>BOOST_CLASS_REQUIRES</tt> macro can be used inside a class
definition to check whether some type models a concept.
<pre>
struct some_class_using_foo {
BOOST_CLASS_REQUIRES(foo, EqualityComparableConcept);
};
</pre>
To add concept checks to the <tt>std::stable_sort()</tt> function the
library implementor would simply insert <tt>function_requires()</tt>
at the top of <tt>std::stable_sort()</tt> to make sure the template
parameter type models <a
href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
RandomAccessIterator</a>. In addition, <tt>std::stable_sort()</tt>
requires that the <tt>value_type</tt> of the iterators be
<a href="http://www.sgi.com/Technology/STL/LessThanComparable.html">
LessThanComparable</a>, so we also use <tt>function_requires()</tt> to
check this.
<pre>
template &lt;class RandomAccessIter&gt;
void stable_sort(RandomAccessIter first, RandomAccessIter last)
{
function_requires&lt; RandomAccessIteratorConcept&lt;RandomAccessIter&gt; &gt;();
typedef typename std::iterator_traits&lt;RandomAccessIter&gt;::value_type value_type;
function_requires&lt; LessThanComparableConcept&lt;value_type&gt; &gt;();
...
}
</pre>
<!-- There are a few places where the SGI STL documentation differs
from the corresponding requirements described in the C++ Standard. In
these cases we use the definition from the C++ Standard. -->
<p>
Some concepts deal with more than one type. In this case the
corresponding concept checking class will have multiple template
parameters. The following example shows how
<tt>function_requires()</tt> is used with the <a
href="../property_map/ReadWritePropertyMap.html">ReadWritePropertyMap</a>
concept which takes two type parameters: a property map and the key
type for the map.
<pre>
template &lt;class IncidenceGraph, class Buffer, class BFSVisitor,
class ColorMap&gt;
void breadth_first_search(IncidenceGraph& g,
typename graph_traits&lt;IncidenceGraph&gt;::vertex_descriptor s,
Buffer& Q, BFSVisitor vis, ColorMap color)
{
typedef typename graph_traits&lt;IncidenceGraph&gt;::vertex_descriptor Vertex;
function_requires&lt; ReadWritePropertyMap&lt;ColorMap, Vertex&gt; &gt;();
...
}
</pre>
As an example of using <tt>class_requires</tt> we look at a concept
check that could be added to <tt>std::vector</tt>. One requirement
that is placed on the element type is that it must be <a
href="http://www.sgi.com/Technology/STL/Assignable.html">Assignable</a>.
We can check this by inserting
<tt>class_requires&lt;AssignableConcept&lt;T&gt; &gt;</tt> at the top
of the definition for <tt>std::vector</tt>.
<pre>
namespace std {
template &lt;class T&gt;
struct vector {
typedef typename class_requires&lt; AssignableConcept&lt;T&gt; &gt;::check req;
...
};
}
</pre>
Although the concept checks are designed for use by generic library
implementors, they can also be useful to end users. Sometimes one may
not be sure whether some type models a particular concept. This can
easily be checked by creating a small program and using
<tt>function_requires()</tt> with the type and concept in question.
The file <a
href="./stl_concept_checks.cpp"><tt>stl_concept_checks.cpp</tt></a>
gives and example of applying the concept checks to STL
containers. The file is listed here:
<pre>
#include &lt;boost/concept_checks.hpp&gt;
#include &lt;iterator&gt;
#include &lt;set&gt;
#include &lt;map&gt;
#include &lt;vector&gt;
#include &lt;list&gt;
#include &lt;deque&gt;
int
main()
{
typedef std::vector&lt;int&gt; Vector;
typedef std::deque&lt;int&gt; Deque;
typedef std::list&lt;int&gt; List;
function_requires&lt; Mutable_RandomAccessContainer&lt;Vector&gt; &gt;();
function_requires&lt; BackInsertionSequence&lt;Vector&gt; &gt;();
function_requires&lt; Mutable_RandomAccessContainer&lt;Deque&gt; &gt;();
function_requires&lt; FrontInsertionSequence&lt;Deque&gt; &gt;();
function_requires&lt; BackInsertionSequence&lt;Deque&gt; &gt;();
function_requires&lt; Mutable_ReversibleContainer&lt;List&gt; &gt;();
function_requires&lt; FrontInsertionSequence&lt;List&gt; &gt;();
function_requires&lt; BackInsertionSequence&lt;List&gt; &gt;();
typedef std::set&lt;int&gt; Set;
typedef std::multiset&lt;int&gt; MultiSet;
typedef std::map&lt;int,int&gt; Map;
typedef std::multimap&lt;int,int&gt; MultiMap;
function_requires&lt; SortedAssociativeContainer&lt;Set&gt; &gt;();
function_requires&lt; SimpleAssociativeContainer&lt;Set&gt; &gt;();
function_requires&lt; UniqueAssociativeContainer&lt;Set&gt; &gt;();
function_requires&lt; SortedAssociativeContainer&lt;MultiSet&gt; &gt;();
function_requires&lt; SimpleAssociativeContainer&lt;MultiSet&gt; &gt;();
function_requires&lt; MultipleAssociativeContainer&lt;MultiSet&gt; &gt;();
function_requires&lt; SortedAssociativeContainer&lt;Map&gt; &gt;();
function_requires&lt; UniqueAssociativeContainer&lt;Map&gt; &gt;();
function_requires&lt; PairAssociativeContainer&lt;Map&gt; &gt;();
function_requires&lt; SortedAssociativeContainer&lt;MultiMap&gt; &gt;();
function_requires&lt; MultipleAssociativeContainer&lt;MultiMap&gt; &gt;();
function_requires&lt; PairAssociativeContainer&lt;MultiMap&gt; &gt;();
return 0;
}
</pre>
<h2><a name="creating-concept-checks">Creating Concept Checking Classes</a></h2>
As an example of how to create a concept checking class, we look
at how to create the corresponding checks for the
<a href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
RandomAccessIterator</a> concept. First, as a convention we name the
concept checking class after the concept, and add the suffix
``<tt>_concept</tt>''. Note that the <tt>REQUIRE</tt> macro expects
the suffix to be there. Next we must define a member function named
<tt>constraints()</tt> in which we will exercise the valid expressions
of the concept. The <tt>REQUIRE</tt> macro expects this function's
signature to appear exactly as it is appears below: a <tt>void</tt>
non-const member function with no parameters.
<p>
The first part of the <tt>constraints()</tt> function includes
the requirements that correspond to the <i>refinement</i> relationship
between <a href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
RandomAccessIterator</a> and the concepts which it builds upon:
<a href="http://www.sgi.com/Technology/STL/BidirectionalIterator.html">
BidirectionalIterator</a> and
<a href="http://www.sgi.com/Technology/STL/LessThanComparable.html">
LessThanComparable</a>. We could have instead used
<tt>CLASS_REQUIRES</tt> and placed these requirements in the class
body, however <tt>CLASS_REQUIRES</tt> uses C++ language features that
are less portable.
<p>
Next we check that the <tt>iterator_category</tt> of the iterator is
either <tt>std::random_access_iterator_tag</tt> or a derived class.
After that we write out some code that corresponds to the valid
expressions of the <a
href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
RandomAccessIterator</a> concept. Typedefs can also be added to
enforce the associated types of the concept.
<pre>
template &lt;class Iter&gt;
struct RandomAccessIterator_concept
{
void constraints() {
function_requires&lt; BidirectionalIteratorConcept&lt;Iter&gt; &gt;();
function_requires&lt; LessThanComparableConcept&lt;Iter&gt; &gt;();
function_requires&lt; ConvertibleConcept&lt;
typename std::iterator_traits&lt;Iter&gt;::iterator_category,
std::random_access_iterator_tag&gt; &gt;();
i += n;
i = i + n; i = n + i;
i -= n;
i = i - n;
n = i - j;
i[n];
}
Iter a, b;
Iter i, j;
typename std::iterator_traits&lt;Iter&gt;::difference_type n;
};
}
</pre>
One potential pitfall in designing concept checking classes is using
more expressions in the constraint function than necessary. For
example, it is easy to accidentally use the default constructor to
create the objects that will be needed in the expressions (and not all
concepts require a default constructor). This is the reason we write
the constraint function as a member function of a class. The objects
involved in the expressions are declared as data members of the class.
Since objects of the constraints class template are never
instantiated, the default constructor for the concept checking class
is never instantiated. Hence the data member's default constructors
are never instantiated (C++ Standard Section 14.7.1 9).
<h2><a name="concept-covering">Concept Covering and Archetypes</a></h2>
We have discussed how it is important to select the minimal
requirements (concepts) for the inputs to a component, but it is
equally important to verify that the chosen concepts <i>cover</i> the
algorithm. That is, any possible user error should be caught by the
concept checks and not let slip through. Concept coverage can be
verified through the use of <i>archetype classes</i>. An archetype
class is an exact implementation of the interface associated with a
particular concept. The run-time behavior of the archetype class is
not important, the functions can be left empty. A simple test program
can then be compiled with the archetype classes as the inputs to the
component. If the program compiles then one can be sure that the
concepts cover the component.
The following code shows the archetype class for the <a
href="http://www.sgi.com/Technology/STL/trivial.html">TrivialIterator</a>
concept. Some care must be taken to ensure that the archetype is an
exact match to the concept. For example, the concept states that the
return type of <tt>operator*()</tt> must be convertible to the value
type. It does not state the more stringent requirement that the return
type be <tt>T&amp;</tt> or <tt>const T&amp;</tt>. That means it would be a
mistake to use <tt>T&amp;</tt> or <tt>const T&amp;</tt> for the return type
of the archetype class. The correct approach is to create an
artificial return type that is convertible to <tt>T</tt>, as we have
done here with <tt>input_proxy</tt>. The validity of the archetype
class test is completely dependent on it being an exact match with the
concept, which must be verified by careful (manual) inspection.
<pre>
template &lt;class T&gt;
struct input_proxy {
operator T() { return t; }
static T t;
};
template &lt;class T&gt;
class trivial_iterator_archetype
{
typedef trivial_iterator_archetype self;
public:
trivial_iterator_archetype() { }
trivial_iterator_archetype(const self&) { }
self& operator=(const self&) { return *this; }
friend bool operator==(const self&, const self&) { return true; }
friend bool operator!=(const self&, const self&) { return true; }
input_proxy&lt;T&gt; operator*() { return input_proxy&lt;T&gt;(); }
};
namespace std {
template &lt;class T&gt;
struct iterator_traits&lt; trivial_iterator_archetype&lt;T&gt; &gt;
{
typedef T value_type;
};
}
</pre>
Generic algorithms are often tested by being instantiated with a
number of common input types. For example, one might apply
<tt>std::stable_sort()</tt> with basic pointer types as the iterators.
Though appropriate for testing the run-time behavior of the algorithm,
this is not helpful for ensuring concept coverage because C++ types
never match particular concepts, they often provide much more than the
minimal functionality required by any one concept. That is, even
though the function template compiles with a given type, the concept
requirements may still fall short of covering the functions actual
requirements. This is why it is important to compile with archetype
classes in addition to testing with common input types.
<p>
The following is an excerpt from <a
href="./stl_concept_covering.cpp"><tt>stl_concept_covering.cpp</tt></a>
that shows how archetypes can be used to check the requirement
documentation for
<a href="http://www.sgi.com/Technology/STL/stable_sort.html">
<tt>std::stable_sort()</tt></a>. In this case, it looks like the <a
href="../utility/CopyConstructible.html">CopyConstructible</a> and <a
href="../utility/Assignable.html">Assignable</a> requirements were
forgotten in the SGI STL documentation (try removing those
archetypes). The Boost archetype classes have been designed so that
they can be layered. In this example the value type of the iterator
is composed out of three archetypes. In the archetype class reference
below, template parameters named <tt>Base</tt> indicate where the
layered archetype can be used.
<pre>
{
typedef less_than_comparable_archetype&lt;
copy_constructible_archetype&lt;
assignable_archetype&lt;&gt; &gt; &gt; ValueType;
random_access_iterator_archetype&lt;ValueType&gt; ri;
std::stable_sort(ri, ri);
}
</pre>
<h2><a name="programming-with-concepts">Programming with Concepts</a></h2>
The process of deciding how to group requirements into concepts and
deciding which concepts to use in each algorithm is perhaps the most
difficult (yet most important) part of building a generic library.
A guiding principle to use during this process is one we
call the <i>requirement minimization principle</i>.
<p>
<b>Requirement Minimization Principle:</b> Minimize the requirements
on the input parameters of a component to increase its reusability.
<p>
There is natural tension in this statement. By definition, the input
parameters must be used by the component in order for the component to
accomplish its task (by ``component'' we mean a function or class
template). The challenge then is to implement the component in such a
way that makes the fewest assumptions (the minimum requirements) about
the inputs while still accomplishing the task.
<p>
The traditional notions of <i>abstraction</i> tie in directly to the
idea of minimal requirements. The more abstract the input, the fewer
the requirements. Thus, concepts are simply the embodiment of generic
abstract data types in C++ template programming.
<p>
When designing the concepts for some problem domain it is important to
keep in mind their purpose, namely to express the requirements for the
input to the components. With respect to the requirement minimization
principle, this means we want to minimize concepts.
<p>
It is important to note, however, that
minimizing concepts does not mean simply
reducing the number of valid expressions
in the concept.
For example, the
<tt>std::stable_sort()</tt> function requires that the value type of
the iterator be <a
href="http://www.sgi.com/Technology/STL/LessThanComparable.html">
LessThanComparable</a>, which not only
includes <tt>operator&lt;()</tt>, but also <tt>operator&gt;()</tt>,
<tt>operator&lt;=()</tt>, and <tt>operator&gt;=()</tt>.
It turns out that <tt>std::stable_sort()</tt> only uses
<tt>operator&lt;()</tt>. The question then arises: should
<tt>std::stable_sort()</tt> be specified in terms of the concept
<a
href="http://www.sgi.com/Technology/STL/LessThanComparable.html">
LessThanComparable</a> or in terms of a concept that only
requires <tt>operator&lt;()</tt>?
<p>
We remark first that the use of <a
href="http://www.sgi.com/Technology/STL/LessThanComparable.html">
LessThanComparable</a> does not really violate the requirement
minimization principle because all of the other operators can be
trivially implemented in terms of <tt>operator&lt;()</tt>. By
``trivial'' we mean one line of code and a constant run-time cost.
More fundamentally, however, the use of <a
href="http://www.sgi.com/Technology/STL/LessThanComparable.html">
LessThanComparable</a> does not violate the requirement minimization
principle because all of the comparison operators (<tt>&lt;</tt>,
<tt>></tt>, <tt><=</tt>, <tt>>=</tt>) are conceptually equivalent (in
a mathematical sense). Adding conceptually equivalent valid
expressions is not a violation of the requirement minimization
principle because no new semantics are being added --- only new
syntax. The added syntax increases re-usability.
<p>
For example,
the
maintainer of the <tt>std::stable_sort()</tt> may some day change the
implementation in places to use <tt>operator>()</tt> instead of
<tt>operator<()</tt>, since, after all, they are equivalent. Since the
requirements are part of the public interface, such a change could
potentially break client code. If instead
<a
href="http://www.sgi.com/Technology/STL/LessThanComparable.html">
LessThanComparable</a> is given as the requirement for
<tt>std::stable_sort()</tt>, then the maintainer is given a reasonable
amount of flexibility within which to work.
<p>
Minimality in concepts is a property associated with the underlying
semantics of the problem domain being represented. In the problem
domain of basic containers, requiring traversal in a single direction
is a smaller requirement than requiring traversal in both directions
(hence the distinction between <a
href="http://www.sgi.com/Technology/STL/ForwardIterator.html">
ForwardIterator</a> and
<a
href="http://www.sgi.com/Technology/STL/BidirectionalIterator.html">
BidirectionalIterator</a>). The semantic difference can be easily seen
in the difference between the set of concrete data structures that
have forward iterators versus the set that has bidirectional
iterators. For example, singly-linked lists would fall in the set of
data structures having forward iterators, but not bidirectional
iterators. In addition, the set of algorithms that one can implement
using only forward iterators is quite different than the set that can
be implemented with bidirectional iterators. Because of this, it is
important to factor families of requirements into rather fine-grained
concepts. For example, the requirements for iterators are factored
into the six STL iterator concepts (trivial, output, input, forward,
bidirectional, and random access).
<h2><a name="implementation">Implementation</a></h2>
Ideally we would like to catch, and indicate, the concept violation at
the point of instantiation. As mentioned in D&amp;E[<a
href="bibliography.html#stroustrup94:_design_evolution">2</a>], the error
can be caught by exercising all of the requirements needed by the
function template. Exactly how the requirements (the valid
expressions in particular) are exercised is a tricky issue, since we
want the code to be compiled --- <i>but not executed</i>. Our
approach is to exercise the requirements in a separate function that
is assigned to a function pointer. In this case, the compiler will
instantiate the function but will not actually invoke it. In
addition, an optimizing compiler will remove the pointer assignment as
``dead code'' (though the run-time overhead added by the assignment
would be trivial in any case). It might be conceivable for a compiler
to skip the semantic analysis and compilation of the constraints
function in the first place, which would make our function pointer
technique ineffective. However, this is unlikely because removal of
unnecessary code and functions is typically done in later stages of a
compiler. We have successfully used the function pointer technique
with GNU C++, Microsoft Visual C++, and several EDG-based compilers
(KAI C++, SGI MIPSpro). The following code shows how this technique
can be applied to the <tt>std::stable_sort()</tt> function:
<pre>
template &lt;class RandomAccessIterator&gt;
void stable_sort_constraints(RandomAccessIterator i) {
typename std::iterator_traits&lt;RandomAccessIterator&gt;
::difference_type n;
i += n; // exercise the requirements for RandomAccessIterator
...
}
template &lt;class RandomAccessIterator&gt;
void stable_sort(RandomAccessIterator first, RandomAccessIterator last) {
typedef void (*fptr_type)(RandomAccessIterator);
fptr_type x = &stable_sort_constraints;
...
}
</pre>
There is often a large set of requirements that need to be checked,
and it would be cumbersome for the library implementor to write
constraint functions like <tt>stable_sort_constraints()</tt> for every
public function. Instead, we group sets of valid expressions
together, according to the definitions of the corresponding concepts.
For each concept we define a concept checking class template where the
template parameter is for the type to be checked. The class contains
a <tt>contraints()</tt> member function which exercises all of the
valid expressions of the concept. The objects used in the constraints
function, such as <tt>n</tt> and <tt>i</tt>, are declared as data
members of the concept checking class.
<pre>
template &lt;class Iter&gt;
struct RandomAccessIterator_concept {
void constraints() {
i += n;
...
}
typename std::iterator_traits&lt;RandomAccessIterator&gt;
::difference_type n;
Iter i;
...
};
</pre>
We can still use the function pointer mechanism to cause instantiation
of the constraints function, however now it will be a member function
pointer. To make it easy for the library implementor to invoke the
concept checks, we wrap the member function pointer mechanism in a
function named <tt>function_requires()</tt>. The following code
snippet shows how to use <tt>function_requires()</tt> to make sure
that the iterator is a
<a
href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
RandomAccessIterator</a>.
<pre>
template &lt;class RandomAccessIter&gt;
void stable_sort(RandomAccessIter first, RandomAccessIter last)
{
function_requires< RandomAccessIteratorConcept<RandomAccessIter> >();
...
}
</pre>
The definition of the <tt>function_requires()</tt> is as follows. The
<tt>Concept</tt> is the concept checking class that has been
instantiated with the modeling type. We assign the address of the
constraints member function to the function pointer <tt>x</tt>, which
causes the instantiation of the constraints function and checking of
the concept's valid expressions. We then assign <tt>x</tt> to
<tt>x</tt> to avoid unused variable compiler warnings, and wrap
everything in a do-while loop to prevent name collisions.
<pre>
template <class Concept>
void function_requires()
{
void (Concept::*x)() = BOOST_FPTR Concept::constraints;
ignore_unused_variable_warning(x);
}
</pre>
To check the type parameters of class templates, we provide the
<tt>class_requires</tt> class which can be used inside the body of a
class definition (whereas <tt>function_requires()</tt> can only be
used inside of a function body). <tt>class_requires</tt> declares a
nested class template, where the template parameter is a function
pointer. We then use the nested class type in a typedef with the
function pointer type of the constraint function as the template
argument.
<pre>
template &lt;class Concept&gt;
class class_requires
{
typedef void (Concept::* function_pointer)();
template &lt;function_pointer Fptr&gt;
struct dummy_struct { };
public:
typedef dummy_struct&lt; BOOST_FPTR Concept::constraints &gt; check;
};
</pre>
<tt>class_requires</tt> was not used in the implementation of the
Boost Concept Checking Library concept checks because several
compilers do not implement template parameters of function pointer
type.
<h2><a name="reference">Reference</a></h2>
<h3><a name="functions">Functions</a></h3>
<pre>
template &lt;class Concept&gt;
void function_requires();
</pre>
<h3><a name="classes">Classes</a></h3>
<pre>
template &lt;class Concept&gt;
struct class_requires {
typedef ... check;
};
</pre>
<pre>
// Make sure that <i>Type1</i> and <i>Type2</i> are exactly the same type.
// If they are not, then the nested typedef for <tt>type</tt> will
// not exist and cause a compiler error.
template &lt;class Type1, class Type2&gt;
struct require_same {
typedef ... type;
};
// usage example
typedef typedef require_same<int,int>::type req1; // this will compile OK
typedef typedef require_same<int,float>::type req1; // this will cause a compiler error
</pre>
<h3><a name="basic-concepts">Basic Concept Checking Classes</a></h3>
<pre>
template &lt;class T&gt; struct Integer_concept; // Is T a built-in integer type?
template &lt;class T&gt; struct SignedIntegerConcept; // Is T a built-in signed integer type?
template &lt;class X, class Y&gt; struct ConvertibleConcept; // Is X convertible to Y?
template &lt;class T&gt; struct AssignableConcept;
template &lt;class T&gt; struct DefaultConstructibleConcept;
template &lt;class T&gt; struct CopyConstructibleConcept;
template &lt;class T&gt; struct BooleanConcept;
template &lt;class T&gt; struct EqualityComparableConcept;
// Is class T equality comparable on the left side with type Left?
template &lt;class T, class Left&gt; struct LeftEqualityComparableConcept;
template &lt;class T&gt; struct LessThanComparableConcept;
</pre>
<h3><a name="iterator-concepts">Iterator Concept Checking Classes</a></h3>
<pre>
template &lt;class Iter&gt; struct TrivialIteratorConcept;
template &lt;class Iter&gt; struct Mutable_TrivialIteratorConcept;
template &lt;class Iter&gt; struct InputIteratorConcept;
template &lt;class Iter, class T&gt; struct OutputIteratorConcept;
template &lt;class Iter&gt; struct ForwardIteratorConcept;
template &lt;class Iter&gt; struct Mutable_ForwardIteratorConcept;
template &lt;class Iter&gt; struct BidirectionalIteratorConcept;
template &lt;class Iter&gt; struct Mutable_BidirectionalIteratorConcept;
template &lt;class Iter&gt; struct RandomAccessIteratorConcept;
template &lt;class Iter&gt; struct Mutable_RandomAccessIteratorConcept;
</pre>
<h3><a name="function-object-concepts">Function Object Concept Checking Classes</a></h3>
<pre>
template &lt;class Func, class Return&gt; struct GeneratorConcept;
template &lt;class Func, class Return, class Arg&gt; struct UnaryFunctionConcept;
template &lt;class Func, class Return, class First, class Second&gt; struct BinaryFunctionConcept;
template &lt;class Func, class Arg&gt; struct UnaryPredicateConcept;
template &lt;class Func, class First, class Second&gt; struct BinaryPredicateConcept;
template &lt;class Func, class First, class Second&gt; struct Const_BinaryPredicateConcept {;
</pre>
<h3><a name="container-concepts">Container Concept Checking Classes</a></h3>
<pre>
template &lt;class C&gt; struct ContainerConcept;
template &lt;class C&gt; struct Mutable_ContainerConcept;
template &lt;class C&gt; struct ForwardContainerConcept;
template &lt;class C&gt; struct Mutable_ForwardContainerConcept;
template &lt;class C&gt; struct ReversibleContainerConcept;
template &lt;class C&gt; struct Mutable_ReversibleContainerConcept;
template &lt;class C&gt; struct RandomAccessContainerConcept;
template &lt;class C&gt; struct Mutable_RandomAccessContainerConcept;
template &lt;class C&gt; struct SequenceConcept;
template &lt;class C&gt; struct FrontInsertionSequenceConcept;
template &lt;class C&gt; struct BackInsertionSequenceConcept;
template &lt;class C&gt; struct AssociativeContainerConcept;
template &lt;class C&gt; struct UniqueAssociativeContainerConcept;
template &lt;class C&gt; struct MultipleAssociativeContainerConcept;
template &lt;class C&gt; struct SimpleAssociativeContainerConcept;
template &lt;class C&gt; struct PairAssociativeContainerConcept;
template &lt;class C&gt; struct SortedAssociativeContainerConcept;
</pre>
<h3><a name="basic-archetype">Basic Archetype Classes</a></h3>
<pre>
class null_archetype; // A type that models no concepts.
template &lt;class Base = null_archetype&gt; class default_constructible_archetype;
template &lt;class Base = null_archetype&gt; class assignable_archetype;
template &lt;class Base = null_archetype&gt; class copy_constructible_archetype;
template &lt;class Left, class Base = null_archetype&gt; class left_equality_comparable_archetype;
template &lt;class Base = null_archetype&gt; class equality_comparable_archetype;
template &lt;class T, class Base = null_archetype&gt; class convertible_to_archetype;
</pre>
<h3><a name="iterator-archetype">Iterator Archetype Classes</a></h3>
<pre>
template &lt;class ValueType&gt; class trivial_iterator_archetype;
template &lt;class ValueType&gt; class mutable_trivial_iterator_archetype;
template &lt;class ValueType&gt; class input_iterator_archetype;
template &lt;class ValueType&gt; class forward_iterator_archetype;
template &lt;class ValueType&gt; class bidirectional_iterator_archetype;
template &lt;class ValueType&gt; class random_access_iterator_archetype;
</pre>
<h3><a name="function-object-archetype">Function Object Archetype Classes</a></h3>
<pre>
template &lt;class Arg, class Return&gt; class unary_function_archetype;
template &lt;class Arg1, class Arg2, class Return&gt; class binary_function_archetype;
template &lt;class Arg&gt; class predicate_archetype;
template &lt;class Arg1, class Arg2&gt; class binary_predicate_archetype;
</pre>
<h3><a name="container-archetype">Container Archetype Classes</a></h3>
<pre>
UNDER CONSTRUCTION
</pre>
<h2><a name="history">History</a></h2>
An earlier version of this concept checking system was developed by
the author while working at SGI in their C++ compiler and library
group. The earlier version is now part of the SGI STL distribution. The
boost concept checking library differs from the concept checking in
the SGI STL in that the definition of concept checking classes has
been greatly simplified, at the price of less helpful verbiage in the
error messages.
<h2><a name="publications">Publications</a></h2>
<ul>
<li><a href="http://www.oonumerics.org/tmpw00/">
C++ Template Workshop 2000</a>, Concept Checking</li>
</ul>
<h2><a name="acknowledgements">Acknowledgements</a></h2>
The idea to use function pointers to cause instantiation is due to
Alexander Stepanov. I am not sure of the origin of the idea to use
expressions to do up-front checking of templates, but it did appear in
D&amp;E[
<a href="bibliography.html#stroustrup94:_design_evolution">2</a>].
Thanks to Matt Austern for his excellent documentation and
organization of the STL concepts, upon which these concept checks
are based. Thanks to Boost members for helpful comments and
reviews.
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF=http://www.boost.org/people/jeremy_siek.htm>Jeremy Siek</A>,
Univ.of Notre Dame (<A
HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)
</TD></TR></TABLE>
</BODY>
</HTML>

View File

@ -1,23 +0,0 @@
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/pending/concept_checks.hpp>
/*
This file verifies that function_requires() of the Boost Concept
Checking Library catches errors when it is suppose to.
*/
struct foo { };
int
main()
{
boost::function_requires< boost::EqualityComparableConcept<foo> >();
return 0;
}

View File

@ -1,185 +0,0 @@
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/pending/concept_checks.hpp>
#include <boost/pending/concept_archetypes.hpp>
/*
This file verifies that the BOOST_FUNCTION_REQUIRES macros of the
Boost Concept Checking Library do not cause errors when they are not
suppose to and verifies that the concept archetypes meet the
requirements of their matching concepts.
*/
int
main()
{
using namespace boost;
//===========================================================================
// Basic Concepts
{
typedef default_constructible_archetype<> foo;
function_requires< DefaultConstructibleConcept<foo> >();
}
{
typedef assignable_archetype<> foo;
function_requires< AssignableConcept<foo> >();
}
{
typedef copy_constructible_archetype<> foo;
function_requires< CopyConstructibleConcept<foo> >();
}
{
typedef sgi_assignable_archetype<> foo;
function_requires< SGIAssignableConcept<foo> >();
}
{
typedef copy_constructible_archetype<> foo;
typedef convertible_to_archetype<foo> convertible_to_foo;
function_requires< ConvertibleConcept<convertible_to_foo, foo> >();
}
{
function_requires< ConvertibleConcept<boolean_archetype, bool> >();
}
{
typedef equality_comparable_archetype<> foo;
function_requires< EqualityComparableConcept<foo> >();
}
{
typedef less_than_comparable_archetype<> foo;
function_requires< LessThanComparableConcept<foo> >();
}
{
typedef comparable_archetype<> foo;
function_requires< ComparableConcept<foo> >();
}
{
typedef equal_op_first_archetype<> First;
typedef equal_op_second_archetype<> Second;
function_requires< EqualOpConcept<First, Second> >();
}
{
typedef not_equal_op_first_archetype<> First;
typedef not_equal_op_second_archetype<> Second;
function_requires< NotEqualOpConcept<First, Second> >();
}
{
typedef less_than_op_first_archetype<> First;
typedef less_than_op_second_archetype<> Second;
function_requires< LessThanOpConcept<First, Second> >();
}
{
typedef less_equal_op_first_archetype<> First;
typedef less_equal_op_second_archetype<> Second;
function_requires< LessEqualOpConcept<First, Second> >();
}
{
typedef greater_than_op_first_archetype<> First;
typedef greater_than_op_second_archetype<> Second;
function_requires< GreaterThanOpConcept<First, Second> >();
}
{
typedef greater_equal_op_first_archetype<> First;
typedef greater_equal_op_second_archetype<> Second;
function_requires< GreaterEqualOpConcept<First, Second> >();
}
{
typedef copy_constructible_archetype<> Return;
typedef plus_op_first_archetype<Return> First;
typedef plus_op_second_archetype<Return> Second;
function_requires< PlusOpConcept<Return, First, Second> >();
}
//===========================================================================
// Function Object Concepts
{
typedef generator_archetype<null_archetype<> > foo;
function_requires< GeneratorConcept<foo, null_archetype<> > >();
}
{
function_requires< GeneratorConcept< void_generator_archetype, void > >();
}
{
typedef unary_function_archetype<int, int> F;
function_requires< UnaryFunctionConcept<F, int, int> >();
}
{
typedef binary_function_archetype<int, int, int> F;
function_requires< BinaryFunctionConcept<F, int, int, int> >();
}
{
typedef unary_predicate_archetype<int> F;
function_requires< UnaryPredicateConcept<F, int> >();
}
{
typedef binary_predicate_archetype<int, int> F;
function_requires< BinaryPredicateConcept<F, int, int> >();
typedef const_binary_predicate_archetype<int, int> const_F;
function_requires< Const_BinaryPredicateConcept<const_F, int, int> >();
}
//===========================================================================
// Iterator Concepts
{
typedef trivial_iterator_archetype<null_archetype<> > Iter;
function_requires< TrivialIteratorConcept<Iter> >();
}
{
typedef mutable_trivial_iterator_archetype<null_archetype<> > Iter;
function_requires< Mutable_TrivialIteratorConcept<Iter> >();
}
{
typedef input_iterator_archetype<null_archetype<> > Iter;
function_requires< InputIteratorConcept<Iter> >();
}
{
typedef output_iterator_archetype Iter;
function_requires< OutputIteratorConcept<Iter, int> >();
}
{
typedef forward_iterator_archetype<null_archetype<> > Iter;
function_requires< ForwardIteratorConcept<Iter> >();
}
{
typedef forward_iterator_archetype<assignable_archetype<> > Iter;
function_requires< Mutable_ForwardIteratorConcept<Iter> >();
}
{
typedef bidirectional_iterator_archetype<null_archetype<> > Iter;
function_requires< BidirectionalIteratorConcept<Iter> >();
}
{
typedef bidirectional_iterator_archetype<assignable_archetype<> > Iter;
function_requires< Mutable_BidirectionalIteratorConcept<Iter> >();
}
{
typedef random_access_iterator_archetype<null_archetype<> > Iter;
function_requires< RandomAccessIteratorConcept<Iter> >();
}
{
typedef random_access_iterator_archetype<assignable_archetype<> > Iter;
function_requires< Mutable_RandomAccessIteratorConcept<Iter> >();
}
//===========================================================================
// Container Concepts
{
function_requires< ContainerConcept< > >();
}
{
}
return 0;
}

View File

@ -1,131 +1,125 @@
<HTML>
<!--
-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. We make no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
-->
<Head>
<Title>Concept Covering and Archetypes</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<BR Clear>
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000 -->
<!-- Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<h2><a name="concept-covering">Concept Covering and Archetypes</a></h2>
<head>
<meta name="generator" content=
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" />
We have discussed how it is important to select the minimal
requirements (concepts) for the inputs to a component, but it is
equally important to verify that the chosen concepts <i>cover</i> the
algorithm. That is, any possible user error should be caught by the
concept checks and not let slip through. Concept coverage can be
verified through the use of <i>archetype classes</i>. An archetype
class is an exact implementation of the interface associated with a
particular concept. The run-time behavior of the archetype class is
not important, the functions can be left empty. A simple test program
can then be compiled with the archetype classes as the inputs to the
component. If the program compiles then one can be sure that the
concepts cover the component.
<title>Concept Covering and Archetypes</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="../../rst.css" type="text/css" />
</head>
The following code shows the archetype class for the <a
href="http://www.sgi.com/tech/stl/trivial.html">TrivialIterator</a>
concept. Some care must be taken to ensure that the archetype is an
exact match to the concept. For example, the concept states that the
return type of <tt>operator*()</tt> must be convertible to the value
type. It does not state the more stringent requirement that the return
type be <tt>T&amp;</tt> or <tt>const T&amp;</tt>. That means it would be a
mistake to use <tt>T&amp;</tt> or <tt>const T&amp;</tt> for the return type
of the archetype class. The correct approach is to create an
artificial return type that is convertible to <tt>T</tt>, as we have
done here with <tt>input_proxy</tt>. The validity of the archetype
class test is completely dependent on it being an exact match with the
concept, which must be verified by careful (manual) inspection.
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
"#FF0000">
<img src="../../boost.png" alt="C++ Boost" width="277" height=
"86" /><br clear="none" />
<pre>
template &lt;class T&gt;
struct input_proxy {
operator const T&() {
return static_object&lt;T&gt;::get(); // Get a reference without constructing
}
<h2><a name="concept-covering" id="concept-covering">Concept Covering and
Archetypes</a></h2>
<p>We have discussed how it is important to select the minimal requirements
(concepts) for the inputs to a component, but it is equally important to
verify that the chosen concepts <i>cover</i> the algorithm. That is, any
possible user error should be caught by the concept checks and not let slip
through. Concept coverage can be verified through the use of <i>archetype
classes</i>. An archetype class is an exact implementation of the interface
associated with a particular concept. The run-time behavior of the
archetype class is not important, the functions can be left empty. A simple
test program can then be compiled with the archetype classes as the inputs
to the component. If the program compiles then one can be sure that the
concepts cover the component. The following code shows the archetype class
for the <a href="http://www.boost.org/sgi/stl/InputIterator.html">Input
Iterator</a> concept. Some care must be taken to ensure that the archetype
is an exact match to the concept. For example, the concept states that the
return type of <tt>operator*()</tt> must be convertible to the value type.
It does not state the more stringent requirement that the return type be
<tt>T&amp;</tt> or <tt>const T&amp;</tt>. That means it would be a mistake
to use <tt>T&amp;</tt> or <tt>const T&amp;</tt> for the return type of the
archetype class. The correct approach is to create an artificial return
type that is convertible to <tt>T</tt>, as we have done here with
<tt>reference</tt>. The validity of the archetype class test is completely
dependent on it being an exact match with the concept, which must be
verified by careful (manual) inspection.</p>
<pre>
template &lt;class T&gt;
class input_iterator_archetype
{
private:
typedef input_iterator_archetype self;
public:
typedef std::input_iterator_tag iterator_category;
typedef T value_type;
struct reference {
operator const value_type&amp;() const { return static_object&lt;T&gt;::get(); }
};
template &lt;class T&gt;
class trivial_iterator_archetype
{
typedef trivial_iterator_archetype self;
public:
trivial_iterator_archetype() { }
trivial_iterator_archetype(const self&) { }
self& operator=(const self&) { return *this; }
friend bool operator==(const self&, const self&) { return true; }
friend bool operator!=(const self&, const self&) { return true; }
input_proxy&lt;T&gt; operator*() { return input_proxy&lt;T&gt;(); }
};
namespace std {
template &lt;class T&gt;
struct iterator_traits&lt; trivial_iterator_archetype&lt;T&gt; &gt;
{
typedef T value_type;
};
}
typedef const T* pointer;
typedef std::ptrdiff_t difference_type;
self&amp; operator=(const self&amp;) { return *this; }
bool operator==(const self&amp;) const { return true; }
bool operator!=(const self&amp;) const { return true; }
reference operator*() const { return reference(); }
self&amp; operator++() { return *this; }
self operator++(int) { return *this; }
};
</pre>
Generic algorithms are often tested by being instantiated with a
number of common input types. For example, one might apply
<tt>std::stable_sort()</tt> with basic pointer types as the iterators.
Though appropriate for testing the run-time behavior of the algorithm,
this is not helpful for ensuring concept coverage because C++ types
never match particular concepts, they often provide much more than the
minimal functionality required by any one concept. That is, even
though the function template compiles with a given type, the concept
requirements may still fall short of covering the functions actual
requirements. This is why it is important to compile with archetype
classes in addition to testing with common input types.
<p>Generic algorithms are often tested by being instantiated with a number
of common input types. For example, one might apply
<tt>std::stable_sort()</tt> with basic pointer types as the iterators.
Though appropriate for testing the run-time behavior of the algorithm, this
is not helpful for ensuring concept coverage because C++ types never match
particular concepts exactly. Instead, they often provide more than the
minimal functionality required by any one concept. Even though the function
template has concept checks, and compiles with a given type, the checks may
still fall short of covering all the functionality that is actually used.
This is why it is important to compile with archetype classes in addition
to testing with common input types.</p>
<p>
The following is an excerpt from <a
href="./stl_concept_covering.cpp"><tt>stl_concept_covering.cpp</tt></a>
that shows how archetypes can be used to check the requirement
documentation for
<a href="http://www.sgi.com/tech/stl/stable_sort.html">
<tt>std::stable_sort()</tt></a>. In this case, it looks like the <a
href="../utility/CopyConstructible.html">CopyConstructible</a> and <a
href="../utility/Assignable.html">Assignable</a> requirements were
forgotten in the SGI STL documentation (try removing those
archetypes). The Boost archetype classes have been designed so that
they can be layered. In this example the value type of the iterator
is composed out of three archetypes. In the archetype class reference
below, template parameters named <tt>Base</tt> indicate where the
layered archetype can be used.
<pre>
{
typedef less_than_comparable_archetype&lt;
sgi_assignable_archetype&lt;&gt; &gt; ValueType;
random_access_iterator_archetype&lt;ValueType&gt; ri;
std::stable_sort(ri, ri);
}
<p>The following is an excerpt from <a href=
"./stl_concept_covering.cpp"><tt>stl_concept_covering.cpp</tt></a> that
shows how archetypes can be used to check the requirement documentation for
<a href=
"http://www.boost.org/sgi/stl/stable_sort.html"><tt>std::stable_sort()</tt></a>.
In this case, it looks like the <a href=
"../utility/CopyConstructible.html">CopyConstructible</a> and <a href=
"../utility/Assignable.html">Assignable</a> requirements were forgotten in
the SGI STL documentation (try removing those archetypes). The Boost
archetype classes have been designed so that they can be layered. In this
example the value type of the iterator is composed out of three archetypes.
In the <a href="reference.htm#basic-archetype">archetype class
reference</a>, template parameters named <tt>Base</tt> indicate where the
layered archetype paradigm can be used.</p>
<pre>
{
typedef less_than_comparable_archetype&lt;
sgi_assignable_archetype&lt;&gt; &gt; ValueType;
random_access_iterator_archetype&lt;ValueType&gt; ri;
std::stable_sort(ri, ri);
}
</pre>
<a href="./prog_with_concepts.htm">Next: Programming with Concepts</a><br>
<a href="./creating_concepts.htm">Prev: Creating Concept Checking Classes</a>
<p><a href="./prog_with_concepts.htm">Next: Programming with
Concepts</a><br />
<a href="./creating_concepts.htm">Prev: Creating Concept Checking
Classes</a><br />
<hr />
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
</TD></TR></TABLE>
<table>
<tr valign="top">
<td nowrap="nowrap">Copyright &copy; 2000</td>
</BODY>
</HTML>
<td><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
"mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>),
2007 <a href="mailto:dave@boost-consulting.com">David Abrahams</a>.
</tr>
</table>
</body>
</html>

View File

@ -1,110 +1,157 @@
<HTML>
<!--
-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. We make no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
-->
<Head>
<Title>Creating Concept Checking Classes</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<BR Clear>
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000 -->
<!-- Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content=
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" />
<h2><a name="creating-concept-checks">Creating Concept Checking Classes</a></h2>
<title>Creating Concept Checking Classes</title>
<link rel="stylesheet" href="../../rst.css" type="text/css" />
</head>
As an example of how to create a concept checking class, we look
at how to create the corresponding checks for the
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
RandomAccessIterator</a> concept. First, as a convention we name the
concept checking class after the concept, and add the suffix
``<tt>Concept</tt>''. Next we must define a member function named
<tt>constraints()</tt> in which we will exercise the valid expressions
of the concept. <tt>function_requires()</tt> expects this function's
signature to appear exactly as it is appears below: a <tt>void</tt>
non-const member function with no parameters.
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
"#FF0000">
<img src="../../boost.png" alt="C++ Boost" width="277" height=
"86" /><br clear="none" />
<p>
The first part of the <tt>constraints()</tt> function includes
the requirements that correspond to the <i>refinement</i> relationship
between <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
RandomAccessIterator</a> and the concepts which it builds upon:
<a href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">
BidirectionalIterator</a> and
<a href="http://www.sgi.com/tech/stl/LessThanComparable.html">
LessThanComparable</a>. We could have instead used
<tt>BOOST_CLASS_REQUIRE</tt> and placed these requirements in the class
body, however <tt>BOOST_CLASS_REQUIRE</tt> uses C++ language features that
are less portable.
<h2><a name="creating-concept-checks" id="creating-concept-checks">Creating
Concept Checking Classes</a></h2>
<p>
Next we check that the <tt>iterator_category</tt> of the iterator is
either <tt>std::random_access_iterator_tag</tt> or a derived class.
After that we write out some code that corresponds to the valid
expressions of the <a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
RandomAccessIterator</a> concept. Typedefs can also be added to
enforce the associated types of the concept.
<p>As an example of how to create a concept checking class template, we
look at how to create the corresponding checks for the <a href=
"http://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a> concept.
The complete definition is here:</p>
<pre>
template &lt;class X&gt;
struct InputIterator
: Assignable&lt;X&gt;, EqualityComparable&lt;X&gt;
{
private:
typedef std::iterator_traits&lt;X&gt; t;
public:
typedef typename t::value_type value_type;
typedef typename t::difference_type difference_type;
typedef typename t::reference reference;
typedef typename t::pointer pointer;
typedef typename t::iterator_category iterator_category;
<pre>
template &lt;class Iter&gt;
struct RandomAccessIterator_concept
{
void constraints() {
function_requires&lt; BidirectionalIteratorConcept&lt;Iter&gt; &gt;();
function_requires&lt; LessThanComparableConcept&lt;Iter&gt; &gt;();
function_requires&lt; ConvertibleConcept&lt;
typename std::iterator_traits&lt;Iter&gt;::iterator_category,
std::random_access_iterator_tag&gt; &gt;();
i += n;
i = i + n; i = n + i;
i -= n;
i = i - n;
n = i - j;
i[n];
BOOST_CONCEPT_ASSERT((SignedInteger&lt;difference_type&gt;));
BOOST_CONCEPT_ASSERT((Convertible&lt;iterator_category, std::input_iterator_tag&gt;));
BOOST_CONCEPT_USAGE(InputIterator)
{
X j(i); <font color=
"green">// require copy construction</font>
same_type(*i++,v); <font color=
"green">// require postincrement-dereference returning value_type</font>
X&amp; x = ++j; <font color=
"green">// require preincrement returning X&amp;</font>
}
Iter i, j;
typename std::iterator_traits&lt;Iter&gt;::difference_type n;
};
private:
X i;
value_type v;
<font color=
"green">// Type deduction will fail unless the arguments have the same type.</font>
template &lt;typename T&gt;
void same_type(T const&amp;, T const&amp;);
};
</pre>
<h3>Walkthrough</h3>
<p>First, as a convention we name the concept checking class after the
concept. Next, since InputIterator is a refinement of Assignable and
EqualityComparable, we derive its concept checking class from the checking
classes for those other concepts. The library will automatically check for
conformance to Assignable and EqualityComparable whenever it checks the
InputIterator concept.</p>
<p>Next, we declare the concept's <a href=
"http://www.boost.org/more/generic_programming.html#associated_type">associated types</a>
as member typedefs. The associated difference type is required to be a
signed integer, and the iterator category has to be convertible to
std::input_iterator_tag, so we assert those relationships. The syntax for
accessing associated types through the concept-checking template mirrors
the <a href=
"http://www.generic-programming.org/languages/conceptcpp/">proposed</a>
syntax for associated type access in C++0x Finally, we use the
<code>BOOST_CONCEPT_USAGE</code> macro to declare the function that
exercises all the concept's valid expressions. Note that at this point you
may sometimes need to be a little creative: for example, to check that
<code>*i++</code> returns the iterator's value type, we pass both values to
the <code>same_type</code> member function template, which requires both
arguments to have the same type, modulo references and cv-qualification.
It's an imperfect check, but it's better than nothing.</p>
<h3>Values for Usage Patterns Should Be Data Members</h3>
<p>You may be wondering why we declared <code>i</code> and <code>v</code>
as data members in the example above. Why didn't we simply write the
following?</p>
<pre>
BOOST_CONCEPT_USAGE(InputIterator)
{
X i; <font color=
"green">// create the values we need</font>
value_type v;
X j(i); <font color=
"green">// require copy construction</font>
same_type(*i++,v); <font color=
"green">// require postincrement-dereference returning value_type</font>
X&amp; x = ++j; <font color=
"green">// require preincrement returning X&amp;</font>
}
</pre>
One potential pitfall in designing concept checking classes is using
more expressions in the constraint function than necessary. For
example, it is easy to accidentally use the default constructor to
create the objects that will be needed in the expressions (and not all
concepts require a default constructor). This is the reason we write
the constraint function as a member function of a class. The objects
involved in the expressions are declared as data members of the class.
Since objects of the constraints class template are never
instantiated, the default constructor for the concept checking class
is never instantiated. Hence the data member's default constructors
are never instantiated (C++ Standard Section 14.7.1 9).
<p>Unfortunately, that code wouldn't have worked out so well, because it
unintentionally imposes the requirement that <code>X</code> and its value
type are both default-constructible. On the other hand, since instances of
the <code>InputIterator</code> template will never be constructed, the
compiler never has to check how its data members will be constructed (C++
Standard Section 14.7.1 9). For that reason you should <strong>always
declare values needed for usage patterns as data members</strong>.</p>
<p>
<a href="./concept_covering.htm">Next: Concept Covering and Archetypes</a><br>
<a href="./using_concept_check.htm">Prev: Using Concept Checks</a>
<p>These sorts of errors in concept definitions can be detected by the use
of <a href="concept_covering.htm">Concept Archetypes</a>, but it's always
better to avoid them pre-emptively.</p>
<h3>Similarity to Proposed C++0x Language Support for Concepts</h3>
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
</TD></TR></TABLE>
<p>This library's syntaxes for concept refinement and for access of
associated types mirrors the corresponding <a href=
"http://www.generic-programming.org/languages/conceptcpp/">proposed</a>
syntaxes in C++0x. However, C++0x will use
“signatures” rather than usage patterns to
describe the valid operations on types participating in a concept, so when
converting your concept checking classes into language-supported concepts,
you'll need to translate your usage function into a series of
signatures.</p>
</BODY>
</HTML>
<p><a href="./concept_covering.htm">Next: Concept Covering and
Archetypes</a><br />
<a href="./using_concept_check.htm">Prev: Using Concept
Checks</a><br /></p>
<hr />
<table>
<tr valign="top">
<td nowrap="nowrap">Copyright &copy; 2000</td>
<td><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
"mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>),
2007 <a href="mailto:dave@boost-consulting.com">David Abrahams</a>.
</tr>
</table>
</body>
</html>

14
doc/Jamfile.v2 Normal file
View File

@ -0,0 +1,14 @@
project boost/concepts ;
import boostbook : boostbook ;
boostbook concepts : reference/concepts.xml
:
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html
<xsl:param>boost.root=../../../..
;
###############################################################################
alias boostdoc ;
explicit boostdoc ;
alias boostrelease : concepts ;
explicit boostrelease ;

View File

@ -0,0 +1,59 @@
<?xml version="1.0"?>
<concept name="Assignable" category="Utility"><!--
Based on concepts from the SGI Standard Template Library documentation:
Copyright (c) 1996-1999
Silicon Graphics Computer Systems, Inc.
Copyright (c) 1994
Hewlett-Packard Company
--><!--
Copyright 2000-2001 University of Notre Dame du Lac.
Copyright 2001-2002 Indiana University.
Some concepts based on versions from the MTL draft manual and Boost Graph
and Property Map documentation:
Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
-->
<param name="X" role="assignable-type"/>
<models-sentence>The type <arg num="1"/> must be a model of <self/>.</models-sentence>
<description>
<para>Assignable types must have copy constructors,
<code>operator=</code> for assignment, and the <code>swap()</code>
function defined.</para>
</description>
<notation variables="x y">
<sample-value>
<type name="X"/>
</sample-value>
</notation>
<refines const="no" concept="CopyConstructible"/>
<valid-expression name="Assignment">
<assign>
<sample-value><reference-to><type name="X"/></reference-to></sample-value>
<sample-value><const><reference-to><type name="X"/></reference-to></const></sample-value>
</assign>
<return-type>
<require-same-type testable="yes">
<reference-to><type name="X"/></reference-to>
</require-same-type>
</return-type>
<semantics>Require <code>operator=</code></semantics>
</valid-expression>
<valid-expression name="Swap">
<apply-function name="swap">
<sample-value><reference-to><type name="X"/></reference-to></sample-value>
<sample-value><reference-to><type name="X"/></reference-to></sample-value>
</apply-function>
<return-type><require-same-type><type name="void"/></require-same-type></return-type>
<semantics>Require <code>swap()</code> function</semantics>
</valid-expression>
<example-model>
<type name="int"/>
</example-model>
</concept>

View File

@ -0,0 +1,136 @@
<?xml version="1.0"?>
<concept name="BidirectionalIterator" category="Iterator"><!--
Based on concepts from the SGI Standard Template Library documentation:
Copyright (c) 1996-1999
Silicon Graphics Computer Systems, Inc.
Copyright (c) 1994
Hewlett-Packard Company
--><!--
Copyright 2000-2001 University of Notre Dame du Lac.
Copyright 2001-2002 Indiana University.
Some concepts based on versions from the MTL draft manual and Boost Graph
and Property Map documentation:
Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
-->
<param name="Iter" role="iterator-type"/>
<use-header name="iterator"/>
<models-sentence>The iterator type <arg num="1"/> must be a model of <self/>.</models-sentence>
<description>
<para>A bidirectional iterator is an iterator that can read through a sequence
of values. It can move in either direction through the sequence, and can
be either mutable (data pointed to by it can be changed) or not mutable.</para>
<para>An iterator represents a position in a sequence. Therefore, the
iterator can point into the sequence (returning a value when dereferenced
and being incrementable), or be off-the-end (and not dereferenceable or
incrementable).</para>
</description>
<associated-type name="value_type">
<get-member-type name="value_type">
<apply-template name="std::iterator_traits">
<type name="Iter"/>
</apply-template>
</get-member-type>
<description><simpara>The value type of the iterator</simpara></description>
</associated-type>
<refines const="no" concept="ForwardIterator"/>
<notation variables="i j">
<sample-value>
<type name="Iter"/>
</sample-value>
</notation>
<associated-type name="category">
<get-member-type name="iterator_category">
<apply-template name="std::iterator_traits">
<type name="Iter"/>
</apply-template>
</get-member-type>
<description><simpara>The category of the iterator</simpara></description>
</associated-type>
<notation variables="x">
<sample-value>
<type name="value_type"/>
</sample-value>
</notation>
<valid-type-expression name="Category tag">
<description/>
<type name="category"/>
<return-type>
<derived-from testable="yes">
<type name="std::bidirectional_iterator_tag"/>
</derived-from>
</return-type>
</valid-type-expression>
<valid-expression name="Predecrement">
<predecrement>
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
</predecrement>
<return-type>
<require-same-type testable="yes">
<reference-to><type name="Iter"/></reference-to>
</require-same-type>
</return-type>
<precondition><code>i</code> is incrementable (not
off-the-end) and some dereferenceable iterator <code>j</code> exists
such that <code>i == ++j</code></precondition>
</valid-expression>
<valid-expression name="Postdecrement">
<postdecrement>
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
</postdecrement>
<return-type>
<require-same-type testable="yes"><type name="Iter"/></require-same-type>
</return-type>
<precondition>Same as for predecrement</precondition>
<semantics>Equivalent to <code>{Iter j = i; --i; return j;}</code></semantics>
<postcondition><code>i</code> is dereferenceable or
off-the-end</postcondition>
</valid-expression>
<complexity>
All iterator operations must take amortized constant time.
</complexity>
<invariant name="Predecrement must return object">
<code>&amp;i = &amp;(--i)</code>
</invariant>
<invariant name="Unique path through sequence">
<code>i == j</code> implies <code>--i == --j</code>
</invariant>
<invariant name="Increment and decrement are inverses">
<code>++i; --i;</code> and <code>--i; ++i;</code> must end up with the
value of <code>i</code> unmodified, if <code>i</code> both of the
operations in the pair are valid.
</invariant>
<example-model>
<pointer-to>
<type name="T"/>
</pointer-to>
</example-model>
<example-model>
<get-member-type name="iterator">
<apply-template name="std::list">
<type name="T"/>
</apply-template>
</get-member-type>
</example-model>
<see-also concept="RandomAccessIterator"/>
</concept>

View File

@ -0,0 +1,47 @@
<?xml version="1.0"?>
<concept name="CopyConstructible" category="Utility"><!--
Based on concepts from the SGI Standard Template Library documentation:
Copyright (c) 1996-1999
Silicon Graphics Computer Systems, Inc.
Copyright (c) 1994
Hewlett-Packard Company
--><!--
Copyright 2000-2001 University of Notre Dame du Lac.
Copyright 2001-2002 Indiana University.
Some concepts based on versions from the MTL draft manual and Boost Graph
and Property Map documentation:
Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
-->
<param name="X" role="copy-constructible-type"/>
<models-sentence>The type <arg num="1"/> must be a model of <self/>.</models-sentence>
<description>
<para>Copy constructible types must be able to be constructed from another
member of the type.</para>
</description>
<notation variables="x y">
<sample-value>
<type name="X"/>
</sample-value>
</notation>
<valid-expression name="Copy construction">
<construct template-parameters="">
<type name="X"/>
<sample-value><const><reference-to><type name="X"/></reference-to></const></sample-value>
</construct>
<return-type>
<require-same-type testable="yes">
<type name="X"/>
</require-same-type>
</return-type>
<semantics>Require copy constructor.</semantics>
</valid-expression>
<example-model>
<type name="int"/>
</example-model>
</concept>

View File

@ -0,0 +1,40 @@
<?xml version="1.0"?>
<concept name="DefaultConstructible" category="Utility"><!--
Based on concepts from the SGI Standard Template Library documentation:
Copyright (c) 1996-1999
Silicon Graphics Computer Systems, Inc.
Copyright (c) 1994
Hewlett-Packard Company
--><!--
Copyright 2000-2001 University of Notre Dame du Lac.
Copyright 2001-2002 Indiana University.
Some concepts based on versions from the MTL draft manual and Boost Graph
and Property Map documentation:
Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
-->
<param name="X" role="default-constructible-type"/>
<models-sentence>The type <arg num="1"/> must be a model of <self/>.</models-sentence>
<description><para>DefaultConstructible objects only need to have a default
constructor.</para></description>
<valid-expression name="Construction">
<construct template-parameters="">
<type name="X"/>
</construct>
<return-type><require-same-type testable="yes"><type name="X"/></require-same-type></return-type>
<semantics>Construct an instance of the type with default parameters.</semantics>
</valid-expression>
<example-model>
<type name="int"/>
</example-model>
<example-model>
<apply-template name="std::vector">
<type name="double"/>
</apply-template>
</example-model>
</concept>

View File

@ -0,0 +1,63 @@
<?xml version="1.0"?>
<concept name="EqualityComparable" category="Utility"><!--
Based on concepts from the SGI Standard Template Library documentation:
Copyright (c) 1996-1999
Silicon Graphics Computer Systems, Inc.
Copyright (c) 1994
Hewlett-Packard Company
--><!--
Copyright 2000-2001 University of Notre Dame du Lac.
Copyright 2001-2002 Indiana University.
Some concepts based on versions from the MTL draft manual and Boost Graph
and Property Map documentation:
Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
-->
<param name="X" role="comparable-type"/>
<models-sentence>The type <arg num="1"/> must be a model of
<self/>.</models-sentence>
<description><para>Equality Comparable types must have <code>==</code> and
<code>!=</code> operators.</para></description>
<notation variables="x y">
<sample-value>
<type name="X"/>
</sample-value>
</notation>
<valid-expression name="Equality test">
<equal-to>
<sample-value><type name="X"/></sample-value>
<sample-value><type name="X"/></sample-value>
</equal-to>
<return-type>
<convertible-to testable="yes">
<type name="bool"/>
</convertible-to>
</return-type>
</valid-expression>
<valid-expression name="Inequality test">
<not-equal-to>
<sample-value><type name="X"/></sample-value>
<sample-value><type name="X"/></sample-value>
</not-equal-to>
<return-type>
<convertible-to testable="yes">
<type name="bool"/>
</convertible-to>
</return-type>
</valid-expression>
<example-model>
<type name="int"/>
</example-model>
<example-model>
<apply-template name="std::vector">
<type name="int"/>
</apply-template>
</example-model>
</concept>

View File

@ -0,0 +1,174 @@
<?xml version="1.0"?>
<concept name="ForwardIterator" category="Iterator"><!--
Based on concepts from the SGI Standard Template Library documentation:
Copyright (c) 1996-1999
Silicon Graphics Computer Systems, Inc.
Copyright (c) 1994
Hewlett-Packard Company
--><!--
Copyright 2000-2001 University of Notre Dame du Lac.
Copyright 2001-2002 Indiana University.
Some concepts based on versions from the MTL draft manual and Boost Graph
and Property Map documentation:
Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
-->
<param name="Iter" role="iterator-type"/>
<use-header name="iterator"/>
<models-sentence>The iterator type <arg num="1"/> must be a model of <self/>.</models-sentence>
<description>
<para>A forward iterator is an iterator that can read through a sequence of
values. It is multi-pass (old values of the iterator can be
re-used), and can be either mutable (data pointed to by it can be
changed) or not mutable.</para>
<para>An iterator represents a position in a sequence. Therefore, the
iterator can point into the sequence (returning a value when dereferenced
and being incrementable), or be off-the-end (and not dereferenceable or
incrementable).</para>
</description>
<associated-type name="value_type">
<get-member-type name="value_type">
<apply-template name="std::iterator_traits">
<type name="Iter"/>
</apply-template>
</get-member-type>
<description><simpara>The value type of the iterator</simpara></description>
</associated-type>
<refines const="no" concept="InputIterator"/>
<refines const="no" concept="OutputIterator"/>
<!-- DPG doesn't understand this
<models const="no" testable="yes" concept="Input Iterator">
<type name="Iter"/>
</models>
-->
<!--
<models-when-mutable concept="Output Iterator">
<type name="Iter"/>
<type name="value_type"/>
</models-when-mutable>
-->
<notation variables="i j">
<sample-value>
<type name="Iter"/>
</sample-value>
</notation>
<associated-type name="category">
<get-member-type name="iterator_category">
<apply-template name="std::iterator_traits">
<type name="Iter"/>
</apply-template>
</get-member-type>
<description><simpara>The category of the iterator</simpara></description>
</associated-type>
<notation variables="x">
<sample-value>
<type name="value_type"/>
</sample-value>
</notation>
<valid-type-expression name="Category tag">
<description/>
<type name="category"/>
<return-type>
<derived-from testable="yes">
<type name="std::forward_iterator_tag"/>
</derived-from>
</return-type>
</valid-type-expression>
<valid-expression name="Dereference">
<dereference>
<sample-value><type name="Iter"/></sample-value>
</dereference>
<return-type>
<require-same-type testable="yes">
<const-if-not-mutable>
<reference-to><type name="value_type"/></reference-to>
</const-if-not-mutable>
</require-same-type>
</return-type>
<precondition><code>i</code> is incrementable (not
off-the-end)</precondition>
</valid-expression>
<valid-expression name="Member access">
<pointer-member>
<sample-value><type name="Iter"/></sample-value>
</pointer-member>
<return-type>
<require-same-type testable="yes">
<const-if-not-mutable>
<pointer-to><type name="value_type"/></pointer-to>
</const-if-not-mutable>
</require-same-type>
</return-type>
<precondition><code>i</code> is incrementable (not
off-the-end)</precondition>
</valid-expression>
<valid-expression name="Preincrement">
<preincrement>
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
</preincrement>
<return-type>
<require-same-type testable="yes">
<reference-to><type name="Iter"/></reference-to>
</require-same-type>
</return-type>
<precondition><code>i</code> is incrementable (not
off-the-end)</precondition>
</valid-expression>
<valid-expression name="Postincrement">
<postincrement>
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
</postincrement>
<return-type>
<require-same-type testable="yes"><type name="Iter"/></require-same-type>
</return-type>
<precondition><code>i</code> is incrementable (not
off-the-end)</precondition>
<semantics>Equivalent to <code>{Iter j = i; ++i; return j;}</code></semantics>
<postcondition><code>i</code> is dereferenceable or
off-the-end</postcondition>
</valid-expression>
<complexity>
All iterator operations must take amortized constant time.
</complexity>
<invariant name="Predecrement must return object">
<code>&amp;i = &amp;(++i)</code>
</invariant>
<invariant name="Unique path through sequence">
<code>i == j</code> implies <code>++i == ++j</code>
</invariant>
<example-model>
<pointer-to>
<type name="T"/>
</pointer-to>
</example-model>
<example-model>
<get-member-type name="iterator">
<apply-template name="std::hash_set">
<type name="T"/>
</apply-template>
</get-member-type>
</example-model>
<see-also concept="BidirectionalIterator"/>
</concept>

View File

@ -0,0 +1,168 @@
<?xml version="1.0"?>
<concept name="InputIterator" category="Iterator"><!--
Based on concepts from the SGI Standard Template Library documentation:
Copyright (c) 1996-1999
Silicon Graphics Computer Systems, Inc.
Copyright (c) 1994
Hewlett-Packard Company
--><!--
Copyright 2000-2001 University of Notre Dame du Lac.
Copyright 2001-2002 Indiana University.
Some concepts based on versions from the MTL draft manual and Boost Graph
and Property Map documentation:
Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
-->
<param name="Iter" role="iterator-type"/>
<use-header name="iterator"/>
<models-sentence>The iterator type <arg num="1"/> must be a model of <self/>.</models-sentence>
<description>
<para>An input iterator is an iterator that can read through a sequence of
values. It is single-pass (old values of the iterator cannot be
re-used), and read-only.</para>
<para>An input iterator represents a position in a sequence. Therefore, the
iterator can point into the sequence (returning a value when dereferenced
and being incrementable), or be off-the-end (and not dereferenceable or
incrementable).</para>
</description>
<refines const="no" concept="Assignable"/>
<refines const="no" concept="DefaultConstructible"/>
<refines const="no" concept="EqualityComparable"/>
<notation variables="i j">
<sample-value>
<type name="Iter"/>
</sample-value>
</notation>
<associated-type name="value_type">
<get-member-type name="value_type">
<apply-template name="std::iterator_traits">
<type name="Iter"/>
</apply-template>
</get-member-type>
<description><simpara>The value type of the iterator (not necessarily what
<code>*i</code> returns)</simpara></description>
</associated-type>
<associated-type name="difference_type">
<get-member-type name="difference_type">
<apply-template name="std::iterator_traits">
<type name="Iter"/>
</apply-template>
</get-member-type>
<description><simpara>The difference type of the iterator</simpara></description>
</associated-type>
<associated-type name="category">
<get-member-type name="iterator_category">
<apply-template name="std::iterator_traits">
<type name="Iter"/>
</apply-template>
</get-member-type>
<description><simpara>The category of the iterator</simpara></description>
</associated-type>
<notation variables="x">
<sample-value>
<type name="value_type"/>
</sample-value>
</notation>
<valid-type-expression name="Category tag">
<description/>
<type name="category"/>
<return-type>
<derived-from testable="yes">
<type name="std::input_iterator_tag"/>
</derived-from>
<models-as-first-arg const="no" testable="yes" concept="DefaultConstructible"/>
<models-as-first-arg const="no" testable="yes" concept="CopyConstructible"/>
</return-type>
</valid-type-expression>
<valid-type-expression name="Value type copy constructibility">
<description/>
<type name="value_type"/>
<return-type>
<models-as-first-arg const="no" testable="yes" concept="CopyConstructible"/>
</return-type>
</valid-type-expression>
<valid-type-expression name="Difference type properties">
<description/>
<type name="difference_type"/>
<return-type>
<models-as-first-arg const="no" testable="yes" concept="SignedInteger"/>
</return-type>
</valid-type-expression>
<valid-expression name="Dereference">
<dereference>
<sample-value><type name="Iter"/></sample-value>
</dereference>
<return-type>
<convertible-to testable="yes"><type name="value_type"/></convertible-to>
</return-type>
<precondition><code>i</code> is incrementable (not
off-the-end)</precondition>
</valid-expression>
<valid-expression name="Preincrement">
<preincrement>
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
</preincrement>
<return-type>
<require-same-type testable="yes">
<reference-to><type name="Iter"/></reference-to>
</require-same-type>
</return-type>
<precondition><code>i</code> is incrementable (not
off-the-end)</precondition>
</valid-expression>
<valid-expression name="Postincrement">
<postincrement>
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
</postincrement>
<return-type/>
<precondition><code>i</code> is incrementable (not
off-the-end)</precondition>
<semantics>Equivalent to <code>(void)(++i)</code></semantics>
<postcondition><code>i</code> is dereferenceable or
off-the-end</postcondition>
</valid-expression>
<valid-expression name="Postincrement and dereference">
<dereference>
<postincrement>
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
</postincrement>
</dereference>
<return-type>
<convertible-to testable="yes"><type name="value_type"/></convertible-to>
</return-type>
<precondition><code>i</code> is incrementable (not
off-the-end)</precondition>
<semantics>Equivalent to <code>{value_type t = *i; ++i; return t;}</code></semantics>
<postcondition><code>i</code> is dereferenceable or
off-the-end</postcondition>
</valid-expression>
<complexity>
All iterator operations must take amortized constant time.
</complexity>
<example-model>
<type name="std::istream_iterator"/>
</example-model>
<see-also concept="OutputIterator"/>
<see-also concept="ForwardIterator"/>
</concept>

View File

@ -0,0 +1,81 @@
<?xml version="1.0"?>
<concept name="LessThanComparable" category="Utility"><!--
Based on concepts from the SGI Standard Template Library documentation:
Copyright (c) 1996-1999
Silicon Graphics Computer Systems, Inc.
Copyright (c) 1994
Hewlett-Packard Company
--><!--
Copyright 2000-2001 University of Notre Dame du Lac.
Copyright 2001-2002 Indiana University.
Some concepts based on versions from the MTL draft manual and Boost Graph
and Property Map documentation:
Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
-->
<param name="X" role="comparable-type"/>
<models-sentence>The type <arg num="1"/> must be a model of <self/>.</models-sentence>
<description><para>LessThanComparable types must have <code>&lt;</code>,
<code>&gt;</code>, <code>&lt;=</code>, and <code>&gt;=</code>
operators.</para></description>
<notation variables="x y"><sample-value><type name="X"/></sample-value></notation>
<valid-expression name="Less than">
<less-than>
<sample-value><type name="X"/></sample-value>
<sample-value><type name="X"/></sample-value>
</less-than>
<return-type>
<convertible-to testable="yes">
<type name="bool"/>
</convertible-to>
</return-type>
<semantics>Determine if one value is less than another.</semantics>
</valid-expression>
<valid-expression name="Less than or equal">
<less-than-or-equal>
<sample-value><type name="X"/></sample-value>
<sample-value><type name="X"/></sample-value>
</less-than-or-equal>
<return-type>
<convertible-to testable="yes">
<type name="bool"/>
</convertible-to>
</return-type>
<semantics>Determine if one value is less than or equal to another.</semantics>
</valid-expression>
<valid-expression name="Greater than">
<greater-than>
<sample-value><type name="X"/></sample-value>
<sample-value><type name="X"/></sample-value>
</greater-than>
<return-type>
<convertible-to testable="yes">
<type name="bool"/>
</convertible-to>
</return-type>
<semantics>Determine if one value is greater than another.</semantics>
</valid-expression>
<valid-expression name="Greater than or equal to">
<greater-than-or-equal>
<sample-value><type name="X"/></sample-value>
<sample-value><type name="X"/></sample-value>
</greater-than-or-equal>
<return-type>
<convertible-to testable="yes">
<type name="bool"/>
</convertible-to>
</return-type>
<semantics>Determine if one value is greater than or equal to another.</semantics>
</valid-expression>
<example-model>
<type name="int"/>
</example-model>
</concept>

View File

@ -0,0 +1,203 @@
<?xml version="1.0"?>
<concept name="OutputIterator" category="Iterator"><!--
Based on concepts from the SGI Standard Template Library documentation:
Copyright (c) 1996-1999
Silicon Graphics Computer Systems, Inc.
Copyright (c) 1994
Hewlett-Packard Company
--><!--
Copyright 2000-2001 University of Notre Dame du Lac.
Copyright 2001-2002 Indiana University.
Some concepts based on versions from the MTL draft manual and Boost Graph
and Property Map documentation:
Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
-->
<param name="Iter" role="iterator-type"/>
<param name="ValueType" role="value-type"/>
<use-header name="iterator"/>
<models-sentence>The iterator type <arg num="1"/> (with value type <arg num="2"/>) must be a model of <self/>.</models-sentence>
<description>
<para>An output iterator is an iterator that can write a sequence of
values. It is single-pass (old values of the iterator cannot be
re-used), and write-only.</para>
<para>An output iterator represents a position in a (possibly infinite)
sequence. Therefore, the iterator can point into the sequence (returning
a value when dereferenced and being incrementable), or be off-the-end
(and not dereferenceable or incrementable).</para>
</description>
<models const="no" testable="yes" concept="Assignable">
<type name="Iter"/>
</models>
<models const="no" testable="yes" concept="Assignable">
<type name="ValueType"/>
</models>
<models const="no" testable="yes" concept="DefaultConstructible">
<type name="Iter"/>
</models>
<models const="no" testable="yes" concept="EqualityComparable">
<type name="Iter"/>
</models>
<associated-type name="value_type">
<get-member-type name="value_type">
<apply-template name="std::iterator_traits">
<type name="Iter"/>
</apply-template>
</get-member-type>
<description><simpara>The stated value type of the iterator (should be
<code>void</code> for an output iterator that does not model some other
iterator concept).</simpara></description>
</associated-type>
<associated-type name="difference_type">
<get-member-type name="difference_type">
<apply-template name="std::iterator_traits">
<type name="Iter"/>
</apply-template>
</get-member-type>
<description><simpara>The difference type of the iterator</simpara></description>
</associated-type>
<associated-type name="category">
<get-member-type name="iterator_category">
<apply-template name="std::iterator_traits">
<type name="Iter"/>
</apply-template>
</get-member-type>
<description><simpara>The category of the iterator</simpara></description>
</associated-type>
<notation variables="i j">
<sample-value>
<type name="Iter"/>
</sample-value>
</notation>
<notation variables="x">
<sample-value>
<type name="ValueType"/>
</sample-value>
</notation>
<valid-type-expression name="Category tag">
<description/>
<type name="category"/>
<return-type>
<derived-from testable="yes">
<type name="std::output_iterator_tag"/>
</derived-from>
<models-as-first-arg const="no" testable="yes" concept="DefaultConstructible"/>
<models-as-first-arg const="no" testable="yes" concept="CopyConstructible"/>
</return-type>
</valid-type-expression>
<valid-type-expression name="Difference type properties">
<description/>
<type name="difference_type"/>
<return-type>
<models-as-first-arg const="no" testable="yes" concept="SignedInteger"/>
</return-type>
</valid-type-expression>
<valid-expression name="Dereference">
<dereference>
<sample-value><type name="Iter"/></sample-value>
</dereference>
<return-type/>
<precondition><code>i</code> is incrementable (not
off-the-end)</precondition>
</valid-expression>
<valid-expression name="Dereference and assign">
<assign>
<dereference>
<sample-value><type name="Iter"/></sample-value>
</dereference>
<sample-value><const><reference-to><type name="ValueType"/></reference-to></const></sample-value>
</assign>
<return-type/>
<precondition><code>i</code> is incrementable (not
off-the-end)</precondition>
<postcondition><code>*i</code> may not be written to again until it has
been incremented.</postcondition>
</valid-expression>
<valid-expression name="Preincrement">
<preincrement>
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
</preincrement>
<return-type>
<require-same-type testable="yes">
<reference-to><type name="Iter"/></reference-to>
</require-same-type>
</return-type>
<precondition><code>i</code> is incrementable (not
off-the-end)</precondition>
</valid-expression>
<valid-expression name="Postincrement">
<postincrement>
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
</postincrement>
<return-type/>
<precondition><code>i</code> is incrementable (not
off-the-end)</precondition>
<semantics>Equivalent to <code>(void)(++i)</code></semantics>
<postcondition><code>i</code> is dereferenceable or
off-the-end</postcondition>
</valid-expression>
<valid-expression name="Postincrement, dereference, and assign">
<assign>
<dereference>
<postincrement>
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
</postincrement>
</dereference>
<sample-value><const><reference-to><type name="ValueType"/></reference-to></const></sample-value>
</assign>
<return-type/>
<precondition><code>i</code> is incrementable (not
off-the-end)</precondition>
<semantics>Equivalent to <code>{*i = t; ++i;}</code></semantics>
<postcondition><code>i</code> is dereferenceable or
off-the-end</postcondition>
</valid-expression>
<complexity>
All iterator operations must take amortized constant time.
</complexity>
<example-model>
<type name="std::ostream_iterator"/>
<type name="..."/>
</example-model>
<example-model>
<type name="std::insert_iterator"/>
<type name="..."/>
</example-model>
<example-model>
<type name="std::front_insert_iterator"/>
<type name="..."/>
</example-model>
<example-model>
<type name="std::back_insert_iterator"/>
<type name="..."/>
</example-model>
<see-also concept="InputIterator"/>
<see-also concept="ForwardIterator"/>
</concept>

View File

@ -0,0 +1,313 @@
<?xml version="1.0"?>
<concept name="RandomAccessIterator" category="Iterator"><!--
Based on concepts from the SGI Standard Template Library documentation:
Copyright (c) 1996-1999
Silicon Graphics Computer Systems, Inc.
Copyright (c) 1994
Hewlett-Packard Company
--><!--
Copyright 2000-2001 University of Notre Dame du Lac.
Copyright 2001-2002 Indiana University.
Some concepts based on versions from the MTL draft manual and Boost Graph
and Property Map documentation:
Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
-->
<param name="Iter" role="iterator-type"/>
<use-header name="iterator"/>
<models-sentence>The iterator type <arg num="1"/> must be a model of <self/>.</models-sentence>
<description>
<para>A random access iterator is an iterator that can read through
a sequence of values. It can move in either direction through the
sequence (by any amount in constant time), and can be either mutable
(data pointed to by it can be changed) or not mutable.</para>
<para>An iterator represents a position in a sequence. Therefore,
the iterator can point into the sequence (returning a value when
dereferenced and being incrementable), or be off-the-end (and not
dereferenceable or incrementable).</para>
</description>
<associated-type name="value_type">
<get-member-type name="value_type">
<apply-template name="std::iterator_traits">
<type name="Iter"/>
</apply-template>
</get-member-type>
<description><simpara>The value type of the iterator</simpara></description>
</associated-type>
<refines const="no" concept="BidirectionalIterator"/>
<refines const="no" concept="LessThanComparable"/>
<notation variables="i j">
<sample-value>
<type name="Iter"/>
</sample-value>
</notation>
<associated-type name="category">
<get-member-type name="iterator_category">
<apply-template name="std::iterator_traits">
<type name="Iter"/>
</apply-template>
</get-member-type>
<description><simpara>The category of the iterator</simpara></description>
</associated-type>
<associated-type name="difference_type">
<get-member-type name="difference_type">
<apply-template name="std::iterator_traits">
<type name="Iter"/>
</apply-template>
</get-member-type>
<description><simpara>The difference type of the iterator (measure of the number
of steps between two iterators)</simpara></description>
</associated-type>
<notation variables="x">
<sample-value>
<type name="value_type"/>
</sample-value>
</notation>
<notation variables="n">
<sample-value>
<type name="difference_type"/>
</sample-value>
</notation>
<notation variables="int_off">
<sample-value>
<type name="int"/>
</sample-value>
</notation>
<valid-type-expression name="Category tag">
<description/>
<type name="category"/>
<return-type>
<derived-from testable="yes">
<type name="std::random_access_iterator_tag"/>
</derived-from>
</return-type>
</valid-type-expression>
<valid-expression name="Motion">
<add-assign>
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
<sample-value><type name="difference_type"/></sample-value>
</add-assign>
<return-type>
<require-same-type testable="yes">
<reference-to><type name="Iter"/></reference-to>
</require-same-type>
</return-type>
<semantics>Equivalent to applying <code>i++</code> <code>n</code> times
if <code>n</code> is positive, applying <code>i--</code>
<code>-n</code> times if <code>n</code> is negative, and to a null
operation if <code>n</code> is zero.</semantics>
</valid-expression>
<valid-expression name="Motion (with integer offset)">
<add-assign>
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
<sample-value><type name="int"/></sample-value>
</add-assign>
<return-type>
<require-same-type testable="yes">
<reference-to><type name="Iter"/></reference-to>
</require-same-type>
</return-type>
<semantics>Equivalent to applying <code>i++</code> <code>n</code> times
if <code>n</code> is positive, applying <code>i--</code>
<code>-n</code> times if <code>n</code> is negative, and to a null
operation if <code>n</code> is zero.</semantics>
</valid-expression>
<valid-expression name="Subtractive motion">
<subtract-assign>
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
<sample-value><type name="difference_type"/></sample-value>
</subtract-assign>
<return-type>
<require-same-type testable="yes">
<reference-to><type name="Iter"/></reference-to>
</require-same-type>
</return-type>
<semantics>Equivalent to <code>i+=(-n)</code></semantics>
</valid-expression>
<valid-expression name="Subtractive motion (with integer offset)">
<subtract-assign>
<sample-value><reference-to><type name="Iter"/></reference-to></sample-value>
<sample-value><type name="int"/></sample-value>
</subtract-assign>
<return-type>
<require-same-type testable="yes">
<reference-to><type name="Iter"/></reference-to>
</require-same-type>
</return-type>
<semantics>Equivalent to <code>i+=(-n)</code></semantics>
</valid-expression>
<valid-expression name="Addition">
<add>
<sample-value><type name="Iter"/></sample-value>
<sample-value><type name="difference_type"/></sample-value>
</add>
<return-type>
<require-same-type testable="yes"><type name="Iter"/></require-same-type>
</return-type>
<semantics>Equivalent to <code>{Iter j = i; j += n; return j;}</code></semantics>
</valid-expression>
<valid-expression name="Addition with integer">
<add>
<sample-value><type name="Iter"/></sample-value>
<sample-value><type name="int"/></sample-value>
</add>
<return-type>
<require-same-type testable="yes"><type name="Iter"/></require-same-type>
</return-type>
<semantics>Equivalent to <code>{Iter j = i; j += n; return j;}</code></semantics>
</valid-expression>
<valid-expression name="Addition (count first)">
<add>
<sample-value><type name="difference_type"/></sample-value>
<sample-value><type name="Iter"/></sample-value>
</add>
<return-type>
<require-same-type testable="yes"><type name="Iter"/></require-same-type>
</return-type>
<semantics>Equivalent to <code>i + n</code></semantics>
</valid-expression>
<valid-expression name="Addition with integer (count first)">
<add>
<sample-value><type name="int"/></sample-value>
<sample-value><type name="Iter"/></sample-value>
</add>
<return-type>
<require-same-type testable="yes"><type name="Iter"/></require-same-type>
</return-type>
<semantics>Equivalent to <code>i + n</code></semantics>
</valid-expression>
<valid-expression name="Subtraction">
<subtract>
<sample-value><type name="Iter"/></sample-value>
<sample-value><type name="difference_type"/></sample-value>
</subtract>
<return-type>
<require-same-type testable="yes"><type name="Iter"/></require-same-type>
</return-type>
<semantics>Equivalent to <code>i + (-n)</code></semantics>
</valid-expression>
<valid-expression name="Subtraction with integer">
<subtract>
<sample-value><type name="Iter"/></sample-value>
<sample-value><type name="int"/></sample-value>
</subtract>
<return-type>
<require-same-type testable="yes"><type name="Iter"/></require-same-type>
</return-type>
<semantics>Equivalent to <code>i + (-n)</code></semantics>
</valid-expression>
<valid-expression name="Distance">
<subtract>
<sample-value><type name="Iter"/></sample-value>
<sample-value><type name="Iter"/></sample-value>
</subtract>
<return-type>
<require-same-type testable="yes"><type name="difference_type"/></require-same-type>
</return-type>
<semantics>The number of times <code>i</code> must be incremented (or
decremented if the result is negative) to reach <code>j</code>. Not
defined if <code>j</code> is not reachable from
<code>i</code>.</semantics>
</valid-expression>
<valid-expression name="Element access">
<subscript>
<sample-value><type name="Iter"/></sample-value>
<sample-value><type name="difference_type"/></sample-value>
</subscript>
<return-type>
<require-same-type testable="yes">
<const-if-not-mutable>
<reference-to>
<type name="value_type"/>
</reference-to>
</const-if-not-mutable>
</require-same-type>
</return-type>
<semantics>Equivalent to <code>*(i + n)</code></semantics>
</valid-expression>
<valid-expression name="Element access with integer index">
<subscript>
<sample-value><type name="Iter"/></sample-value>
<sample-value><type name="int"/></sample-value>
</subscript>
<return-type>
<require-same-type testable="yes">
<const-if-not-mutable>
<reference-to>
<type name="value_type"/>
</reference-to>
</const-if-not-mutable>
</require-same-type>
</return-type>
<semantics>Equivalent to <code>*(i + n)</code></semantics>
</valid-expression>
<complexity>
All iterator operations must take amortized constant time.
</complexity>
<example-model>
<pointer-to>
<type name="T"/>
</pointer-to>
</example-model>
<example-model>
<get-member-type name="iterator">
<apply-template name="std::vector">
<type name="T"/>
</apply-template>
</get-member-type>
</example-model>
<example-model>
<get-member-type name="const_iterator">
<apply-template name="std::vector">
<type name="T"/>
</apply-template>
</get-member-type>
</example-model>
<example-model>
<get-member-type name="iterator">
<apply-template name="std::deque">
<type name="T"/>
</apply-template>
</get-member-type>
</example-model>
<example-model>
<get-member-type name="const_iterator">
<apply-template name="std::deque">
<type name="T"/>
</apply-template>
</get-member-type>
</example-model>
</concept>

View File

@ -0,0 +1,549 @@
<?xml version="1.0"?>
<concept name="SignedInteger" category="Utility"><!--
Based on concepts from the SGI Standard Template Library documentation:
Copyright (c) 1996-1999
Silicon Graphics Computer Systems, Inc.
Copyright (c) 1994
Hewlett-Packard Company
--><!--
Copyright 2000-2001 University of Notre Dame du Lac.
Copyright 2001-2002 Indiana University.
Some concepts based on versions from the MTL draft manual and Boost Graph
and Property Map documentation:
Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
-->
<param name="T" role="integral-type"/>
<models-sentence>Integer type <arg num="1"/> must be a model of <self/>.</models-sentence>
<refines const="no" concept="CopyConstructible"/>
<refines const="no" concept="Assignable"/>
<refines const="no" concept="DefaultConstructible"/>
<refines const="no" concept="EqualityComparable"/>
<refines const="no" concept="LessThanComparable"/>
<notation variables="x y z">
<sample-value><type name="T"/></sample-value>
</notation>
<notation variables="a b">
<sample-value><type name="int"/></sample-value>
</notation>
<!--
<valid-type-expression name="int-ness">
<documentation>Should this really be required?</documentation>
<type name="T"/>
<return-type>
<require-same-type>
<type name="int"/>
</require-same-type>
</return-type>
</valid-type-expression>
-->
<valid-expression name="Conversion from int">
<construct template-parameters="">
<type name="T"/>
<sample-value><type name="int"/></sample-value>
</construct>
<return-type><require-same-type testable="yes">
<type name="T"/>
</require-same-type></return-type>
</valid-expression>
<valid-expression name="Preincrement">
<preincrement>
<sample-value>
<reference-to><type name="T"/></reference-to>
</sample-value>
</preincrement>
<return-type>
<require-same-type testable="yes">
<reference-to><type name="T"/></reference-to>
</require-same-type>
</return-type>
</valid-expression>
<valid-expression name="Predecrement">
<predecrement>
<sample-value>
<reference-to><type name="T"/></reference-to>
</sample-value>
</predecrement>
<return-type>
<require-same-type testable="yes">
<reference-to><type name="T"/></reference-to>
</require-same-type>
</return-type>
</valid-expression>
<valid-expression name="Postincrement">
<postincrement>
<sample-value>
<reference-to><type name="T"/></reference-to>
</sample-value>
</postincrement>
<return-type>
<require-same-type testable="yes">
<type name="T"/>
</require-same-type>
</return-type>
</valid-expression>
<valid-expression name="Postdecrement">
<postdecrement>
<sample-value>
<reference-to><type name="T"/></reference-to>
</sample-value>
</postdecrement>
<return-type>
<require-same-type testable="yes">
<type name="T"/>
</require-same-type>
</return-type>
</valid-expression>
<valid-expression name="Sum">
<add>
<sample-value>
<type name="T"/>
</sample-value>
<sample-value>
<type name="T"/>
</sample-value>
</add>
<return-type>
<require-same-type testable="yes">
<type name="T"/>
</require-same-type>
</return-type>
</valid-expression>
<valid-expression name="Sum with int">
<add>
<sample-value>
<type name="T"/>
</sample-value>
<sample-value>
<type name="int"/>
</sample-value>
</add>
<return-type>
<require-same-type testable="yes">
<type name="T"/>
</require-same-type>
</return-type>
</valid-expression>
<valid-expression name="Sum-assignment">
<add-assign>
<sample-value>
<reference-to><type name="T"/></reference-to>
</sample-value>
<sample-value>
<type name="T"/>
</sample-value>
</add-assign>
<return-type>
<require-same-type testable="yes">
<reference-to><type name="T"/></reference-to>
</require-same-type>
</return-type>
</valid-expression>
<valid-expression name="Sum-assignment with int">
<add-assign>
<sample-value>
<reference-to><type name="T"/></reference-to>
</sample-value>
<sample-value>
<type name="int"/>
</sample-value>
</add-assign>
<return-type>
<require-same-type testable="yes">
<reference-to><type name="T"/></reference-to>
</require-same-type>
</return-type>
</valid-expression>
<valid-expression name="Difference">
<subtract>
<sample-value>
<type name="T"/>
</sample-value>
<sample-value>
<type name="T"/>
</sample-value>
</subtract>
<return-type>
<require-same-type testable="yes">
<type name="T"/>
</require-same-type>
</return-type>
</valid-expression>
<valid-expression name="Difference with int">
<subtract>
<sample-value>
<type name="T"/>
</sample-value>
<sample-value>
<type name="int"/>
</sample-value>
</subtract>
<return-type>
<require-same-type testable="yes">
<type name="T"/>
</require-same-type>
</return-type>
</valid-expression>
<valid-expression name="Product">
<multiply>
<sample-value>
<type name="T"/>
</sample-value>
<sample-value>
<type name="T"/>
</sample-value>
</multiply>
<return-type>
<require-same-type testable="yes">
<type name="T"/>
</require-same-type>
</return-type>
</valid-expression>
<valid-expression name="Product with int">
<multiply>
<sample-value>
<type name="T"/>
</sample-value>
<sample-value>
<type name="int"/>
</sample-value>
</multiply>
<return-type>
<require-same-type testable="yes">
<type name="T"/>
</require-same-type>
</return-type>
</valid-expression>
<valid-expression name="Product-assignment with int">
<multiply-assign>
<sample-value>
<reference-to><type name="T"/></reference-to>
</sample-value>
<sample-value>
<type name="int"/>
</sample-value>
</multiply-assign>
<return-type>
<require-same-type testable="yes">
<reference-to><type name="T"/></reference-to>
</require-same-type>
</return-type>
</valid-expression>
<valid-expression name="Product with int on left">
<multiply>
<sample-value>
<type name="int"/>
</sample-value>
<sample-value>
<type name="T"/>
</sample-value>
</multiply>
<return-type>
<require-same-type testable="yes">
<type name="T"/>
</require-same-type>
</return-type>
</valid-expression>
<valid-expression name="Quotient">
<divide>
<sample-value>
<type name="T"/>
</sample-value>
<sample-value>
<type name="T"/>
</sample-value>
</divide>
<return-type>
<require-same-type testable="yes">
<type name="T"/>
</require-same-type>
</return-type>
</valid-expression>
<valid-expression name="Quotient with int">
<divide>
<sample-value>
<type name="T"/>
</sample-value>
<sample-value>
<type name="int"/>
</sample-value>
</divide>
<return-type>
<require-same-type testable="yes">
<type name="T"/>
</require-same-type>
</return-type>
</valid-expression>
<valid-expression name="Right-shift">
<shift-right>
<sample-value>
<type name="T"/>
</sample-value>
<sample-value>
<type name="T"/>
</sample-value>
</shift-right>
<return-type>
<require-same-type testable="yes">
<type name="T"/>
</require-same-type>
</return-type>
</valid-expression>
<valid-expression name="Right-shift with int">
<shift-right>
<sample-value>
<type name="T"/>
</sample-value>
<sample-value>
<type name="int"/>
</sample-value>
</shift-right>
<return-type>
<require-same-type testable="yes">
<type name="T"/>
</require-same-type>
</return-type>
</valid-expression>
<valid-expression name="Right-shift-assignment with int">
<shift-right-assign>
<sample-value>
<reference-to><type name="T"/></reference-to>
</sample-value>
<sample-value>
<type name="int"/>
</sample-value>
</shift-right-assign>
<return-type>
<require-same-type testable="yes">
<reference-to><type name="T"/></reference-to>
</require-same-type>
</return-type>
</valid-expression>
<valid-expression name="Less-than comparison">
<less-than>
<sample-value>
<type name="T"/>
</sample-value>
<sample-value>
<type name="T"/>
</sample-value>
</less-than>
<return-type>
<convertible-to testable="yes">
<type name="bool"/>
</convertible-to>
</return-type>
</valid-expression>
<valid-expression name="Less-than comparison with int">
<less-than>
<sample-value>
<type name="T"/>
</sample-value>
<sample-value>
<type name="int"/>
</sample-value>
</less-than>
<return-type>
<convertible-to testable="yes">
<type name="bool"/>
</convertible-to>
</return-type>
</valid-expression>
<valid-expression name="Less-than comparison with size_t">
<less-than>
<sample-value>
<type name="T"/>
</sample-value>
<sample-value>
<type name="std::size_t"/>
</sample-value>
</less-than>
<return-type>
<convertible-to testable="yes">
<type name="bool"/>
</convertible-to>
</return-type>
</valid-expression>
<valid-expression name="Greater-than comparison">
<greater-than>
<sample-value>
<type name="T"/>
</sample-value>
<sample-value>
<type name="T"/>
</sample-value>
</greater-than>
<return-type>
<convertible-to testable="yes">
<type name="bool"/>
</convertible-to>
</return-type>
</valid-expression>
<valid-expression name="Greater-than comparison with int">
<greater-than>
<sample-value>
<type name="T"/>
</sample-value>
<sample-value>
<type name="int"/>
</sample-value>
</greater-than>
<return-type>
<convertible-to testable="yes">
<type name="bool"/>
</convertible-to>
</return-type>
</valid-expression>
<valid-expression name="Less-than-or-equal comparison">
<less-than-or-equal>
<sample-value>
<type name="T"/>
</sample-value>
<sample-value>
<type name="T"/>
</sample-value>
</less-than-or-equal>
<return-type>
<convertible-to testable="yes">
<type name="bool"/>
</convertible-to>
</return-type>
</valid-expression>
<valid-expression name="Less-than-or-equal comparison with int">
<less-than-or-equal>
<sample-value>
<type name="T"/>
</sample-value>
<sample-value>
<type name="int"/>
</sample-value>
</less-than-or-equal>
<return-type>
<convertible-to testable="yes">
<type name="bool"/>
</convertible-to>
</return-type>
</valid-expression>
<valid-expression name="Greater-than-or-equal comparison">
<greater-than-or-equal>
<sample-value>
<type name="T"/>
</sample-value>
<sample-value>
<type name="T"/>
</sample-value>
</greater-than-or-equal>
<return-type>
<convertible-to testable="yes">
<type name="bool"/>
</convertible-to>
</return-type>
</valid-expression>
<valid-expression name="Greater-than-or-equal comparison with int">
<greater-than-or-equal>
<sample-value>
<type name="T"/>
</sample-value>
<sample-value>
<type name="int"/>
</sample-value>
</greater-than-or-equal>
<return-type>
<convertible-to testable="yes">
<type name="bool"/>
</convertible-to>
</return-type>
</valid-expression>
<valid-expression name="Greater-than-or-equal comparison with int on left">
<greater-than-or-equal>
<sample-value>
<type name="int"/>
</sample-value>
<sample-value>
<type name="T"/>
</sample-value>
</greater-than-or-equal>
<return-type>
<convertible-to testable="yes">
<type name="bool"/>
</convertible-to>
</return-type>
</valid-expression>
<valid-expression name="Equality comparison">
<equal-to>
<sample-value>
<type name="T"/>
</sample-value>
<sample-value>
<type name="T"/>
</sample-value>
</equal-to>
<return-type>
<convertible-to testable="yes">
<type name="bool"/>
</convertible-to>
</return-type>
</valid-expression>
<valid-expression name="Equality comparison with int">
<equal-to>
<sample-value>
<type name="T"/>
</sample-value>
<sample-value>
<type name="int"/>
</sample-value>
</equal-to>
<return-type>
<convertible-to testable="yes">
<type name="bool"/>
</convertible-to>
</return-type>
</valid-expression>
<valid-type-expression name="Conversion to int">
<documentation/>
<type name="T"/>
<return-type>
<convertible-to testable="yes">
<type name="int"/>
</convertible-to>
</return-type>
</valid-type-expression>
</concept>

View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library-reference PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<library-reference id="concepts.reference"
xmlns:xi="http://www.w3.org/2001/XInclude"
last-revision="$Date$">
<sectioninfo>
<copyright>
<year>2001</year>
<year>2002</year>
<holder>Indiana University</holder>
</copyright>
<copyright>
<year>2000</year>
<year>2001</year>
<holder>University of Notre Dame du Lac</holder>
</copyright>
<copyright>
<year>2000</year>
<holder>Jeremy Siek</holder>
<holder>Lie-Quan Lee</holder>
<holder>Andrew Lumsdaine</holder>
</copyright>
<copyright>
<year>1996</year>
<year>1997</year>
<year>1998</year>
<year>1999</year>
<holder>Silicon Graphics Computer Systems, Inc.</holder>
</copyright>
<copyright>
<year>1994</year>
<holder>Hewlett-Packard Company</holder>
</copyright>
<legalnotice>
<para>Distributed under the Boost Software License, Version 1.0.
(See accompanying file <filename>LICENSE_1_0.txt</filename> or copy at
<ulink
url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>)
</para>
<para>This product includes software developed at the University
of Notre Dame and the Pervasive Technology Labs at Indiana
University. For technical information contact Andrew Lumsdaine
at the Pervasive Technology Labs at Indiana University. For
administrative and license questions contact the Advanced
Research and Technology Institute at 351 West 10th Street.
Indianapolis, Indiana 46202, phone 317-278-4100, fax
317-274-5902.</para>
<para>Some concepts based on versions from the MTL draft manual
and Boost Graph and Property Map documentation, the SGI Standard
Template Library documentation and the Hewlett-Packard STL,
under the following license:
<blockquote><simpara>Permission to use, copy, modify, distribute and
sell this software and its documentation for any purpose is
hereby granted without fee, provided that the above copyright
notice appears in all copies and that both that copyright
notice and this permission notice appear in supporting
documentation. Silicon Graphics makes no representations
about the suitability of this software for any purpose. It is
provided "as is" without express or implied
warranty.</simpara></blockquote></para>
</legalnotice>
</sectioninfo>
<title>Concept reference</title>
<xi:include href="Assignable.xml"/>
<xi:include href="InputIterator.xml"/>
<xi:include href="OutputIterator.xml"/>
<xi:include href="ForwardIterator.xml"/>
<xi:include href="BidirectionalIterator.xml"/>
<xi:include href="RandomAccessIterator.xml"/>
<xi:include href="DefaultConstructible.xml"/>
<xi:include href="CopyConstructible.xml"/>
<xi:include href="EqualityComparable.xml"/>
<xi:include href="LessThanComparable.xml"/>
<xi:include href="SignedInteger.xml"/>
</library-reference>

View File

@ -1,50 +1,59 @@
<HTML>
<!--
-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. We make no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
-->
<Head>
<Title>Concept Checking Implementation</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<BR Clear>
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000, David Abrahams 2007 -->
<!-- Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<head>
<meta name="generator" content=
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="../../rst.css" type="text/css" />
<h2><a name="implementation">Implementation</a></h2>
<title>Concept Checking Implementation</title>
</head>
Ideally we would like to catch, and indicate, the concept violation at
the point of instantiation. As mentioned in D&amp;E[<a
href="bibliography.htm#stroustrup94:_design_evolution">2</a>], the error
can be caught by exercising all of the requirements needed by the
function template. Exactly how the requirements (the valid
expressions in particular) are exercised is a tricky issue, since we
want the code to be compiled --- <i>but not executed</i>. Our
approach is to exercise the requirements in a separate function that
is assigned to a function pointer. In this case, the compiler will
instantiate the function but will not actually invoke it. In
addition, an optimizing compiler will remove the pointer assignment as
``dead code'' (though the run-time overhead added by the assignment
would be trivial in any case). It might be conceivable for a compiler
to skip the semantic analysis and compilation of the constraints
function in the first place, which would make our function pointer
technique ineffective. However, this is unlikely because removal of
unnecessary code and functions is typically done in later stages of a
compiler. We have successfully used the function pointer technique
with GNU C++, Microsoft Visual C++, and several EDG-based compilers
(KAI C++, SGI MIPSpro). The following code shows how this technique
can be applied to the <tt>std::stable_sort()</tt> function:
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
"#FF0000">
<img src="../../boost.png" alt="C++ Boost" width="277" height=
"86" /><br clear="none" />
<pre>
<h2><a name="warning" id="warning"><font color=
"red">Warning</font></a></h2>
<p><font color="red">This documentation is out-of-date; similar but
newer implementation techniques are now used. This documentation
also refers to components and protocols in the library's old
interface such as <code>BOOST_CLASS_REQUIRES</code>
and <code>constraints()</code> functions, which are still supported
but deprecated.</font></p>
<h2><a name="implementation" id="implementation">Implementation</a></h2>
<p>Ideally we would like to catch, and indicate, the concept violation at
the point of instantiation. As mentioned in D&amp;E[<a href=
"bibliography.htm#stroustrup94:_design_evolution">2</a>], the error can be
caught by exercising all of the requirements needed by the function
template. Exactly how the requirements (the valid expressions in
particular) are exercised is a tricky issue, since we want the code to be
compiled—<i>but not executed</i>. Our approach is to exercise the
requirements in a separate function that is assigned to a function pointer.
In this case, the compiler will instantiate the function but will not
actually invoke it. In addition, an optimizing compiler will remove the
pointer assignment as ``dead code'' (though the run-time overhead added by
the assignment would be trivial in any case). It might be conceivable for a
compiler to skip the semantic analysis and compilation of the constraints
function in the first place, which would make our function pointer
technique ineffective. However, this is unlikely because removal of
unnecessary code and functions is typically done in later stages of a
compiler. We have successfully used the function pointer technique with GNU
C++, Microsoft Visual C++, and several EDG-based compilers (KAI C++, SGI
MIPSpro). The following code shows how this technique can be applied to the
<tt>std::stable_sort()</tt> function:</p>
<pre>
template &lt;class RandomAccessIterator&gt;
void stable_sort_constraints(RandomAccessIterator i)
{
@ -57,26 +66,25 @@ can be applied to the <tt>std::stable_sort()</tt> function:
void stable_sort(RandomAccessIterator first, RandomAccessIterator last)
{
typedef void (*fptr_type)(RandomAccessIterator);
fptr_type x = &stable_sort_constraints;
fptr_type x = &amp;stable_sort_constraints;
...
}
</pre>
There is often a large set of requirements that need to be checked,
and it would be cumbersome for the library implementor to write
constraint functions like <tt>stable_sort_constraints()</tt> for every
public function. Instead, we group sets of valid expressions
together, according to the definitions of the corresponding concepts.
For each concept we define a concept checking class template where the
template parameter is for the type to be checked. The class contains
a <tt>contraints()</tt> member function which exercises all of the
valid expressions of the concept. The objects used in the constraints
function, such as <tt>n</tt> and <tt>i</tt>, are declared as data
members of the concept checking class.
<pre>
<p>There is often a large set of requirements that need to be checked, and
it would be cumbersome for the library implementor to write constraint
functions like <tt>stable_sort_constraints()</tt> for every public
function. Instead, we group sets of valid expressions together, according
to the definitions of the corresponding concepts. For each concept we
define a concept checking class template where the template parameter is
for the type to be checked. The class contains a <tt>constraints()</tt>
member function which exercises all of the valid expressions of the
concept. The objects used in the constraints function, such as <tt>n</tt>
and <tt>i</tt>, are declared as data members of the concept checking
class.</p>
<pre>
template &lt;class Iter&gt;
struct RandomAccessIterator_concept
struct RandomAccessIteratorConcept
{
void constraints()
{
@ -90,18 +98,14 @@ members of the concept checking class.
};
</pre>
We can still use the function pointer mechanism to cause instantiation
of the constraints function, however now it will be a member function
pointer. To make it easy for the library implementor to invoke the
concept checks, we wrap the member function pointer mechanism in a
function named <tt>function_requires()</tt>. The following code
snippet shows how to use <tt>function_requires()</tt> to make sure
that the iterator is a
<a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
RandomAccessIterator</a>.
<pre>
<p>We can still use the function pointer mechanism to cause instantiation
of the constraints function, however now it will be a member function
pointer. To make it easy for the library implementor to invoke the concept
checks, we wrap the member function pointer mechanism in a function named
<tt>function_requires()</tt>. The following code snippet shows how to use
<tt>function_requires()</tt> to make sure that the iterator is a <a href=
"http://www.boost.org/sgi/stl/RandomAccessIterator.html">RandomAccessIterator</a>.</p>
<pre>
template &lt;class Iter&gt;
void stable_sort(Iter first, Iter last)
{
@ -110,16 +114,15 @@ RandomAccessIterator</a>.
}
</pre>
The definition of the <tt>function_requires()</tt> is as follows. The
<tt>Concept</tt> is the concept checking class that has been
instantiated with the modeling type. We assign the address of the
constraints member function to the function pointer <tt>x</tt>, which
causes the instantiation of the constraints function and checking of
the concept's valid expressions. We then assign <tt>x</tt> to
<tt>x</tt> to avoid unused variable compiler warnings, and wrap
everything in a do-while loop to prevent name collisions.
<pre>
<p>The definition of the <tt>function_requires()</tt> is as follows. The
<tt>Concept</tt> is the concept checking class that has been instantiated
with the modeling type. We assign the address of the constraints member
function to the function pointer <tt>x</tt>, which causes the instantiation
of the constraints function and checking of the concept's valid
expressions. We then assign <tt>x</tt> to <tt>x</tt> to avoid unused
variable compiler warnings, and wrap everything in a do-while loop to
prevent name collisions.</p>
<pre>
template &lt;class Concept&gt;
void function_requires()
{
@ -128,17 +131,16 @@ everything in a do-while loop to prevent name collisions.
}
</pre>
To check the type parameters of class templates, we provide the
<tt>BOOST_CLASS_REQUIRE</tt> macro which can be used inside the body of a
class definition (whereas <tt>function_requires()</tt> can only be used
inside of a function body). This macro declares a nested class
template, where the template parameter is a function pointer. We then
use the nested class type in a typedef with the function pointer type
of the constraint function as the template argument. We use the
<tt>type_var</tt> and <tt>concept</tt> names in the nested class and
typedef names to help prevent name collisions.
<pre>
<p>To check the type parameters of class templates, we provide the
<tt>BOOST_CLASS_REQUIRE</tt> macro which can be used inside the body of a
class definition (whereas <tt>function_requires()</tt> can only be used
inside of a function body). This macro declares a nested class template,
where the template parameter is a function pointer. We then use the nested
class type in a typedef with the function pointer type of the constraint
function as the template argument. We use the <tt>type_var</tt> and
<tt>concept</tt> names in the nested class and typedef names to help
prevent name collisions.</p>
<pre>
#define BOOST_CLASS_REQUIRE(type_var, ns, concept) \
typedef void (ns::concept &lt;type_var&gt;::* func##type_var##concept)(); \
template &lt;func##type_var##concept _Tp1&gt; \
@ -148,14 +150,12 @@ typedef names to help prevent name collisions.
concept_checking_typedef_##type_var##concept
</pre>
In addition, there are versions of <tt>BOOST_CLASS_REQUIRE</tt> that
take more arguments, to handle concepts that include interactions
between two or more types. <tt>BOOST_CLASS_REQUIRE</tt> was not used
in the implementation of the BCCL concept checks because some
compilers do not implement template parameters of function pointer
type.
<!-- We decided not to go with this version since it is easier to misuse
<p>In addition, there are versions of <tt>BOOST_CLASS_REQUIRE</tt> that
take more arguments, to handle concepts that include interactions between
two or more types. <tt>BOOST_CLASS_REQUIRE</tt> was not used in the
implementation of the BCCL concept checks because some compilers do not
implement template parameters of function pointer type.
<!-- We decided not to go with this version since it is easier to misuse
To check the type parameters of class templates, we provide the
<tt>class_requires</tt> class which can be used inside the body of a
@ -184,21 +184,22 @@ Boost Concept Checking Library concept checks because several
compilers do not implement template parameters of function pointer
type.
-->
--></p>
<p>
<a href="./reference.htm">Next: Reference</a><br>
<a href="prog_with_concepts.htm">Prev: Programming With Concepts</a>
<p><a href="./reference.htm">Next: Reference</a><br />
<a href="prog_with_concepts.htm">Prev: Programming With
Concepts</a><br /></p>
<hr />
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
</TD></TR></TABLE>
<table>
<tr valign="top">
<td nowrap="nowrap">Copyright &copy; 2000</td>
</BODY>
</HTML>
<td><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
"mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>),
2007 <a href="mailto:dave@boost-consulting.com">David Abrahams</a>.
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,45 @@
// Copyright David Abrahams 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_CONCEPT_ASSERT_DWA2006430_HPP
# define BOOST_CONCEPT_ASSERT_DWA2006430_HPP
# include <boost/config.hpp>
# include <boost/config/workaround.hpp>
// The old protocol used a constraints() member function in concept
// checking classes. If the compiler supports SFINAE, we can detect
// that function and seamlessly support the old concept checking
// classes. In this release, backward compatibility with the old
// concept checking classes is enabled by default, where available.
// The old protocol is deprecated, though, and backward compatibility
// will no longer be the default in the next release.
# if !defined(BOOST_NO_OLD_CONCEPT_SUPPORT) \
&& !defined(BOOST_NO_SFINAE) \
\
&& !(BOOST_WORKAROUND(__GNUC__, == 3) && BOOST_WORKAROUND(__GNUC_MINOR__, < 4))
// Note: gcc-2.96 through 3.3.x have some SFINAE, but no ability to
// check for the presence of particularmember functions.
# define BOOST_OLD_CONCEPT_SUPPORT
# endif
# ifdef BOOST_MSVC
# include <boost/concept/detail/msvc.hpp>
# elif BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564))
# include <boost/concept/detail/borland.hpp>
# else
# include <boost/concept/detail/general.hpp>
# endif
// Usage, in class or function context:
//
// BOOST_CONCEPT_ASSERT((UnaryFunctionConcept<F,bool,int>));
//
# define BOOST_CONCEPT_ASSERT(ModelInParens) \
BOOST_CONCEPT_ASSERT_FN(void(*)ModelInParens)
#endif // BOOST_CONCEPT_ASSERT_DWA2006430_HPP

View File

@ -0,0 +1,16 @@
// Copyright David Abrahams 2009. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_CONCEPT_BACKWARD_COMPATIBILITY_DWA200968_HPP
# define BOOST_CONCEPT_BACKWARD_COMPATIBILITY_DWA200968_HPP
namespace boost
{
namespace concepts {}
# if defined(BOOST_HAS_CONCEPTS) && !defined(BOOST_CONCEPT_NO_BACKWARD_KEYWORD)
namespace concept = concepts;
# endif
} // namespace boost::concept
#endif // BOOST_CONCEPT_BACKWARD_COMPATIBILITY_DWA200968_HPP

View File

@ -0,0 +1,30 @@
// Copyright David Abrahams 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_CONCEPT_DETAIL_BORLAND_DWA2006429_HPP
# define BOOST_CONCEPT_DETAIL_BORLAND_DWA2006429_HPP
# include <boost/preprocessor/cat.hpp>
# include <boost/concept/detail/backward_compatibility.hpp>
namespace boost { namespace concepts {
template <class ModelFnPtr>
struct require;
template <class Model>
struct require<void(*)(Model)>
{
enum { instantiate = sizeof((((Model*)0)->~Model()), 3) };
};
# define BOOST_CONCEPT_ASSERT_FN( ModelFnPtr ) \
enum \
{ \
BOOST_PP_CAT(boost_concept_check,__LINE__) = \
boost::concepts::require<ModelFnPtr>::instantiate \
}
}} // namespace boost::concept
#endif // BOOST_CONCEPT_DETAIL_BORLAND_DWA2006429_HPP

View File

@ -0,0 +1,34 @@
// Copyright David Abrahams 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_CONCEPT_DETAIL_CONCEPT_DEF_DWA200651_HPP
# define BOOST_CONCEPT_DETAIL_CONCEPT_DEF_DWA200651_HPP
# include <boost/preprocessor/seq/for_each_i.hpp>
# include <boost/preprocessor/seq/enum.hpp>
# include <boost/preprocessor/comma_if.hpp>
# include <boost/preprocessor/cat.hpp>
#endif // BOOST_CONCEPT_DETAIL_CONCEPT_DEF_DWA200651_HPP
// BOOST_concept(SomeName, (p1)(p2)...(pN))
//
// Expands to "template <class p1, class p2, ...class pN> struct SomeName"
//
// Also defines an equivalent SomeNameConcept for backward compatibility.
// Maybe in the next release we can kill off the "Concept" suffix for good.
# define BOOST_concept(name, params) \
template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename,~,params) > \
struct name; /* forward declaration */ \
\
template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename,~,params) > \
struct BOOST_PP_CAT(name,Concept) \
: name< BOOST_PP_SEQ_ENUM(params) > \
{ \
}; \
\
template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename,~,params) > \
struct name
// Helper for BOOST_concept, above.
# define BOOST_CONCEPT_typename(r, ignored, index, t) \
BOOST_PP_COMMA_IF(index) typename t

View File

@ -0,0 +1,5 @@
// Copyright David Abrahams 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
# undef BOOST_concept_typename
# undef BOOST_concept

View File

@ -0,0 +1,98 @@
// Copyright David Abrahams 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_CONCEPT_DETAIL_GENERAL_DWA2006429_HPP
# define BOOST_CONCEPT_DETAIL_GENERAL_DWA2006429_HPP
# include <boost/config.hpp>
# include <boost/preprocessor/cat.hpp>
# include <boost/concept/detail/backward_compatibility.hpp>
# ifdef BOOST_OLD_CONCEPT_SUPPORT
# include <boost/concept/detail/has_constraints.hpp>
# include <boost/type_traits/conditional.hpp>
# endif
// This implementation works on Comeau and GCC, all the way back to
// 2.95
namespace boost { namespace concepts {
template <class ModelFn>
struct requirement_;
namespace detail
{
template <void(*)()> struct instantiate {};
}
template <class Model>
struct requirement
{
# if defined(BOOST_GCC) && (BOOST_GCC >= 110000)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wnonnull"
# endif
static void failed() { ((Model*)0)->~Model(); }
# if defined(BOOST_GCC) && (BOOST_GCC >= 110000)
# pragma GCC diagnostic pop
# endif
};
struct failed {};
template <class Model>
struct requirement<failed ************ Model::************>
{
# if defined(BOOST_GCC) && (BOOST_GCC >= 110000)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wnonnull"
# endif
static void failed() { ((Model*)0)->~Model(); }
# if defined(BOOST_GCC) && (BOOST_GCC >= 110000)
# pragma GCC diagnostic pop
# endif
};
# ifdef BOOST_OLD_CONCEPT_SUPPORT
template <class Model>
struct constraint
{
# if defined(BOOST_GCC) && (BOOST_GCC >= 110000)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wnonnull"
# endif
static void failed() { ((Model*)0)->constraints(); }
# if defined(BOOST_GCC) && (BOOST_GCC >= 110000)
# pragma GCC diagnostic pop
# endif
};
template <class Model>
struct requirement_<void(*)(Model)>
: boost::conditional<
concepts::not_satisfied<Model>::value
, constraint<Model>
, requirement<failed ************ Model::************>
>::type
{};
# else
// For GCC-2.x, these can't have exactly the same name
template <class Model>
struct requirement_<void(*)(Model)>
: requirement<failed ************ Model::************>
{};
# endif
# define BOOST_CONCEPT_ASSERT_FN( ModelFnPtr ) \
typedef ::boost::concepts::detail::instantiate< \
&::boost::concepts::requirement_<ModelFnPtr>::failed> \
BOOST_PP_CAT(boost_concept_check,__LINE__) \
BOOST_ATTRIBUTE_UNUSED
}}
#endif // BOOST_CONCEPT_DETAIL_GENERAL_DWA2006429_HPP

View File

@ -0,0 +1,50 @@
// Copyright David Abrahams 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_CONCEPT_DETAIL_HAS_CONSTRAINTS_DWA2006429_HPP
# define BOOST_CONCEPT_DETAIL_HAS_CONSTRAINTS_DWA2006429_HPP
# include <boost/type_traits/integral_constant.hpp>
# include <boost/config/workaround.hpp>
# include <boost/concept/detail/backward_compatibility.hpp>
namespace boost { namespace concepts {
namespace detail
{
// Here we implement the metafunction that detects whether a
// constraints metafunction exists
typedef char yes;
typedef char (&no)[2];
template <class Model, void (Model::*)()>
struct wrap_constraints {};
#if BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580) || defined(__CUDACC__)
// Work around the following bogus error in Sun Studio 11, by
// turning off the has_constraints function entirely:
// Error: complex expression not allowed in dependent template
// argument expression
inline no has_constraints_(...);
#else
template <class Model>
inline yes has_constraints_(Model*, wrap_constraints<Model,&Model::constraints>* = 0);
inline no has_constraints_(...);
#endif
}
// This would be called "detail::has_constraints," but it has a strong
// tendency to show up in error messages.
template <class Model>
struct not_satisfied
{
BOOST_STATIC_CONSTANT(
bool
, value = sizeof( detail::has_constraints_((Model*)0) ) == sizeof(detail::yes) );
typedef boost::integral_constant<bool, value> type;
};
}} // namespace boost::concepts::detail
#endif // BOOST_CONCEPT_DETAIL_HAS_CONSTRAINTS_DWA2006429_HPP

View File

@ -0,0 +1,123 @@
// Copyright David Abrahams 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP
# define BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP
# include <boost/preprocessor/cat.hpp>
# include <boost/concept/detail/backward_compatibility.hpp>
# include <boost/config.hpp>
# ifdef BOOST_OLD_CONCEPT_SUPPORT
# include <boost/concept/detail/has_constraints.hpp>
# include <boost/type_traits/conditional.hpp>
# endif
# ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable:4100)
# endif
namespace boost { namespace concepts {
template <class Model>
struct check
{
virtual void failed(Model* x)
{
x->~Model();
}
};
# ifndef BOOST_NO_PARTIAL_SPECIALIZATION
struct failed {};
template <class Model>
struct check<failed ************ Model::************>
{
virtual void failed(Model* x)
{
x->~Model();
}
};
# endif
# ifdef BOOST_OLD_CONCEPT_SUPPORT
namespace detail
{
// No need for a virtual function here, since evaluating
// not_satisfied below will have already instantiated the
// constraints() member.
struct constraint {};
}
template <class Model>
struct require
: boost::conditional<
not_satisfied<Model>::value
, detail::constraint
# ifndef BOOST_NO_PARTIAL_SPECIALIZATION
, check<Model>
# else
, check<failed ************ Model::************>
# endif
>::type
{};
# else
template <class Model>
struct require
# ifndef BOOST_NO_PARTIAL_SPECIALIZATION
: check<Model>
# else
: check<failed ************ Model::************>
# endif
{};
# endif
# if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
//
// The iterator library sees some really strange errors unless we
// do things this way.
//
template <class Model>
struct require<void(*)(Model)>
{
virtual void failed(Model*)
{
require<Model>();
}
};
# define BOOST_CONCEPT_ASSERT_FN( ModelFnPtr ) \
enum \
{ \
BOOST_PP_CAT(boost_concept_check,__LINE__) = \
sizeof(::boost::concepts::require<ModelFnPtr>) \
}
# else // Not vc-7.1
template <class Model>
require<Model>
require_(void(*)(Model));
# define BOOST_CONCEPT_ASSERT_FN( ModelFnPtr ) \
enum \
{ \
BOOST_PP_CAT(boost_concept_check,__LINE__) = \
sizeof(::boost::concepts::require_((ModelFnPtr)0)) \
}
# endif
}}
# ifdef BOOST_MSVC
# pragma warning(pop)
# endif
#endif // BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP

View File

@ -0,0 +1,93 @@
// Copyright David Abrahams 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_CONCEPT_REQUIRES_DWA2006430_HPP
# define BOOST_CONCEPT_REQUIRES_DWA2006430_HPP
# include <boost/config.hpp>
# include <boost/concept/assert.hpp>
# include <boost/preprocessor/seq/for_each.hpp>
namespace boost {
// unaryfunptr_arg_type from parameter/aux_/parenthesized_type.hpp
namespace ccheck_aux {
// A metafunction that transforms void(*)(T) -> T
template <class UnaryFunctionPointer>
struct unaryfunptr_arg_type;
template <class Arg>
struct unaryfunptr_arg_type<void(*)(Arg)>
{
typedef Arg type;
};
template <>
struct unaryfunptr_arg_type<void(*)(void)>
{
typedef void type;
};
} // namespace ccheck_aux
// Template for use in handwritten assertions
template <class Model, class More>
struct requires_ : More
{
BOOST_CONCEPT_ASSERT((Model));
};
// Template for use by macros, where models must be wrapped in parens.
// This isn't in namespace detail to keep extra cruft out of resulting
// error messages.
template <class ModelFn>
struct _requires_
{
enum { value = 0 };
BOOST_CONCEPT_ASSERT_FN(ModelFn);
};
template <int check, class Result>
struct Requires_ : ::boost::ccheck_aux::unaryfunptr_arg_type<Result>
{
};
# if BOOST_WORKAROUND(BOOST_INTEL_WIN, BOOST_TESTED_AT(1010))
# define BOOST_CONCEPT_REQUIRES_(r,data,t) | (::boost::_requires_<void(*)t>::value)
# else
# define BOOST_CONCEPT_REQUIRES_(r,data,t) + (::boost::_requires_<void(*)t>::value)
# endif
#if defined(NDEBUG)
# define BOOST_CONCEPT_REQUIRES(models, result) \
typename ::boost::ccheck_aux::unaryfunptr_arg_type<void(*)result>::type
#elif BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564))
// Same thing as below without the initial typename
# define BOOST_CONCEPT_REQUIRES(models, result) \
::boost::Requires_< \
(0 BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_REQUIRES_, ~, models)), \
::boost::ccheck_aux::unaryfunptr_arg_type<void(*)result> \
>::type
#else
// This just ICEs on MSVC6 :(
# define BOOST_CONCEPT_REQUIRES(models, result) \
typename ::boost::Requires_< \
(0 BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_REQUIRES_, ~, models)), \
void(*)result \
>::type
#endif
// C++0x proposed syntax changed. This supports an older usage
#define BOOST_CONCEPT_WHERE(models,result) BOOST_CONCEPT_REQUIRES(models,result)
} // namespace boost::concept_check
#endif // BOOST_CONCEPT_REQUIRES_DWA2006430_HPP

View File

@ -0,0 +1,43 @@
// Copyright David Abrahams 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_CONCEPT_USAGE_DWA2006919_HPP
# define BOOST_CONCEPT_USAGE_DWA2006919_HPP
# include <boost/concept/assert.hpp>
# include <boost/config/workaround.hpp>
# include <boost/concept/detail/backward_compatibility.hpp>
namespace boost { namespace concepts {
template <class Model>
struct usage_requirements
{
# if defined(BOOST_GCC) && (BOOST_GCC >= 110000)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wnonnull"
# endif
~usage_requirements() { ((Model*)0)->~Model(); }
# if defined(BOOST_GCC) && (BOOST_GCC >= 110000)
# pragma GCC diagnostic pop
# endif
};
# if BOOST_WORKAROUND(__GNUC__, <= 3)
# define BOOST_CONCEPT_USAGE(model) \
model(); /* at least 2.96 and 3.4.3 both need this :( */ \
BOOST_CONCEPT_ASSERT((boost::concepts::usage_requirements<model>)); \
~model()
# else
# define BOOST_CONCEPT_USAGE(model) \
BOOST_CONCEPT_ASSERT((boost::concepts::usage_requirements<model>)); \
~model()
# endif
}} // namespace boost::concepts
#endif // BOOST_CONCEPT_USAGE_DWA2006919_HPP

View File

@ -1,9 +1,8 @@
//
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
// (C) Copyright Jeremy Siek 2000.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Revision History:
//
@ -16,8 +15,10 @@
#define BOOST_CONCEPT_ARCHETYPES_HPP
#include <boost/config.hpp>
#include <boost/iterator.hpp>
#include <boost/config/workaround.hpp>
#include <functional>
#include <iterator> // iterator tags
#include <cstddef> // std::ptrdiff_t
namespace boost {
@ -51,12 +52,18 @@ namespace boost {
// is really quite innocent. The name of this class needs to be
// changed.
template <class T>
class static_object {
class static_object
{
public:
static T& get() {
static char d[sizeof(T)];
return *reinterpret_cast<T*>(d);
}
static T& get()
{
#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564))
return *reinterpret_cast<T*>(0);
#else
static char d[sizeof(T)];
return *reinterpret_cast<T*>(d);
#endif
}
};
template <class Base = null_archetype<> >
@ -258,25 +265,25 @@ namespace boost {
struct optag2 { };
struct optag3 { };
#define BOOST_DEFINE_BINARY_PREDICATE_ARCHETYPE(OP, NAME) \
template <class Base = null_archetype<>, class Tag = optag1 > \
class NAME##_first_archetype : public Base { \
public: \
NAME##_first_archetype(detail::dummy_constructor x) : Base(x) { } \
}; \
\
template <class Base = null_archetype<>, class Tag = optag1 > \
class NAME##_second_archetype : public Base { \
public: \
NAME##_second_archetype(detail::dummy_constructor x) : Base(x) { } \
}; \
\
template <class BaseFirst, class BaseSecond, class Tag> \
boolean_archetype \
operator OP (const NAME##_first_archetype<BaseFirst, Tag>&, \
const NAME##_second_archetype<BaseSecond, Tag>&) \
{ \
return boolean_archetype(static_object<detail::dummy_constructor>::get()); \
#define BOOST_DEFINE_BINARY_PREDICATE_ARCHETYPE(OP, NAME) \
template <class Base = null_archetype<>, class Tag = optag1 > \
class NAME##_first_archetype : public Base { \
public: \
NAME##_first_archetype(detail::dummy_constructor x) : Base(x) { } \
}; \
\
template <class Base = null_archetype<>, class Tag = optag1 > \
class NAME##_second_archetype : public Base { \
public: \
NAME##_second_archetype(detail::dummy_constructor x) : Base(x) { } \
}; \
\
template <class BaseFirst, class BaseSecond, class Tag> \
boolean_archetype \
operator OP (const NAME##_first_archetype<BaseFirst, Tag>&, \
const NAME##_second_archetype<BaseSecond, Tag>&) \
{ \
return boolean_archetype(static_object<detail::dummy_constructor>::get()); \
}
BOOST_DEFINE_BINARY_PREDICATE_ARCHETYPE(==, equal_op)
@ -402,90 +409,38 @@ namespace boost {
//===========================================================================
// Iterator Archetype Classes
template <class T>
struct input_proxy {
operator const T&() { return static_object<T>::get(); }
};
template <class T>
class trivial_iterator_archetype
{
typedef trivial_iterator_archetype self;
public:
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
typedef T value_type;
typedef void reference;
typedef void pointer;
typedef void difference_type;
typedef void iterator_category;
#endif
trivial_iterator_archetype() { }
self& operator=(const self&) { return *this; }
bool operator==(const self&) const { return true; }
bool operator!=(const self&) const { return true; }
input_proxy<T> operator*() const { return input_proxy<T>(); }
};
} // namespace boost
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
namespace std {
template <class T>
struct iterator_traits< boost::trivial_iterator_archetype<T> >
{
typedef T value_type;
};
}
#endif
namespace boost {
template <class T>
struct input_output_proxy {
input_output_proxy<T>& operator=(const T&) { return *this; }
operator const T&() { return static_object<T>::get(); }
};
template <class T>
class mutable_trivial_iterator_archetype
{
typedef mutable_trivial_iterator_archetype self;
public:
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
typedef T value_type;
typedef void reference;
typedef void pointer;
typedef void difference_type;
typedef void iterator_category;
#endif
mutable_trivial_iterator_archetype() { }
self& operator=(const self&) { return *this; }
bool operator==(const self&) const { return true; }
bool operator!=(const self&) const { return true; }
input_output_proxy<T> operator*() const { return input_output_proxy<T>(); }
};
} // namespace boost
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
namespace std {
template <class T>
struct iterator_traits< boost::mutable_trivial_iterator_archetype<T> >
{
typedef T value_type;
};
}
#endif
namespace boost {
template <class T>
template <class T, int I = 0>
class input_iterator_archetype
{
public:
private:
typedef input_iterator_archetype self;
public:
typedef std::input_iterator_tag iterator_category;
typedef T value_type;
struct reference {
operator const value_type&() const { return static_object<T>::get(); }
};
typedef const T* pointer;
typedef std::ptrdiff_t difference_type;
self& operator=(const self&) { return *this; }
bool operator==(const self&) const { return true; }
bool operator!=(const self&) const { return true; }
reference operator*() const { return reference(); }
self& operator++() { return *this; }
self operator++(int) { return *this; }
};
template <class T>
class input_iterator_archetype_no_proxy
{
private:
typedef input_iterator_archetype_no_proxy self;
public:
typedef std::input_iterator_tag iterator_category;
typedef T value_type;
typedef const T& reference;
typedef const T* pointer;
typedef std::ptrdiff_t difference_type;
input_iterator_archetype() { }
self& operator=(const self&) { return *this; }
bool operator==(const self&) const { return true; }
bool operator!=(const self&) const { return true; }
@ -494,7 +449,7 @@ namespace boost {
self operator++(int) { return *this; }
};
template <class T>
template <class T>
struct output_proxy {
output_proxy& operator=(const T&) { return *this; }
};
@ -522,6 +477,30 @@ namespace boost {
output_iterator_archetype() { }
};
template <class T>
class input_output_iterator_archetype
{
private:
typedef input_output_iterator_archetype self;
struct in_out_tag : public std::input_iterator_tag, public std::output_iterator_tag { };
public:
typedef in_out_tag iterator_category;
typedef T value_type;
struct reference {
reference& operator=(const T&) { return *this; }
operator value_type() { return static_object<T>::get(); }
};
typedef const T* pointer;
typedef std::ptrdiff_t difference_type;
input_output_iterator_archetype() { }
self& operator=(const self&) { return *this; }
bool operator==(const self&) const { return true; }
bool operator!=(const self&) const { return true; }
reference operator*() const { return reference(); }
self& operator++() { return *this; }
self operator++(int) { return *this; }
};
template <class T>
class forward_iterator_archetype
{
@ -531,7 +510,7 @@ namespace boost {
typedef std::forward_iterator_tag iterator_category;
typedef T value_type;
typedef const T& reference;
typedef T* pointer;
typedef T const* pointer;
typedef std::ptrdiff_t difference_type;
forward_iterator_archetype() { }
self& operator=(const self&) { return *this; }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,25 @@
// Copyright David Abrahams 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_CONCEPT_CHECK_BORLAND_DWA2006429_HPP
# define BOOST_CONCEPT_CHECK_BORLAND_DWA2006429_HPP
namespace boost {
template <class ModelFn>
struct concept_check;
template <class Model>
struct concept_check<void(*)(Model)>
{
enum { instantiate = sizeof((((Model*)0)->~Model()), 3) };
};
# define BOOST_CONCEPT_ASSERT( ModelInParens ) \
enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \
boost::concept_check<void(*)ModelInParens>::instantiate \
}
} // namespace boost::concept_checking
#endif // BOOST_CONCEPT_CHECK_BORLAND_DWA2006429_HPP

View File

@ -0,0 +1,82 @@
// Copyright David Abrahams 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP
# define BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP
# ifdef BOOST_OLD_CONCEPT_SUPPORT
# include <boost/concept_check/has_constraints.hpp>
# include <boost/type_traits/conditional.hpp>
# endif
// This implementation works on GCC and Comeau, but has actually been
// fairly carefully tuned to work on GCC versions starting with
// gcc-2.95.x. If you're trying to get an additional compiler to pass
// the tests you might consider breaking out a separate gcc.hpp and
// starting over on the general case.
namespace boost
{
namespace concept_checking
{
template <void(*)()> struct instantiate {};
}
template <class ModelFn> struct concept_check_;
template <class Model>
void concept_check_failed()
{
((Model*)0)->~Model();
}
template <class Model>
struct concept_check
{
concept_checking::instantiate<concept_check_failed<Model> > x;
enum { instantiate = 1 };
};
# ifdef BOOST_OLD_CONCEPT_SUPPORT
template <class Model>
void constraint_check_failed()
{
((Model*)0)->constraints();
}
template <class Model>
struct constraint_check
{
concept_checking::instantiate<constraint_check_failed<Model> > x;
enum { instantiate = 1 };
};
template <class Model>
struct concept_check_<void(*)(Model)>
: conditional<
concept_checking::has_constraints<Model>::value
, constraint_check<Model>
, concept_check<Model>
>::type
{};
# else
template <class Model>
struct concept_check_<void(*)(Model)>
: concept_check<Model>
{};
# endif
// Usage, in class or function context:
//
// BOOST_CONCEPT_ASSERT((UnaryFunctionConcept<F,bool,int>));
# define BOOST_CONCEPT_ASSERT( ModelInParens ) \
enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \
::boost::concept_check_<void(*) ModelInParens>::instantiate \
}
}
#endif // BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP

View File

@ -0,0 +1,31 @@
// Copyright David Abrahams 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_CONCEPT_CHECK_HAS_CONSTRAINTS_DWA2006429_HPP
# define BOOST_CONCEPT_CHECK_HAS_CONSTRAINTS_DWA2006429_HPP
namespace boost { namespace concept_checking {
// Here we implement the "metafunction" that detects whether a
// constraints metafunction exists
typedef char yes;
typedef char (&no)[2];
template <class Model, void (Model::*)()>
struct wrap_constraints {};
template <class Model>
inline yes has_constraints_(Model*, wrap_constraints<Model,&Model::constraints>* = 0);
inline no has_constraints_(...);
template <class Model>
struct has_constraints
{
BOOST_STATIC_CONSTANT(
bool
, value = sizeof( concept_checking::has_constraints_((Model*)0) ) == 1 );
};
}} // namespace boost::concept_checking
#endif // BOOST_CONCEPT_CHECK_HAS_CONSTRAINTS_DWA2006429_HPP

View File

@ -0,0 +1,90 @@
// Copyright David Abrahams 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP
# define BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP
# ifdef BOOST_OLD_CONCEPT_SUPPORT
# include <boost/concept_check/has_constraints.hpp>
# include <boost/type_traits/conditional.hpp>
# endif
namespace boost
{
namespace concept_checking
{
template <class Model>
struct concept_check_
{
virtual void failed(Model* x)
{
x->~Model();
}
};
}
# ifdef BOOST_OLD_CONCEPT_SUPPORT
namespace concept_checking
{
template <class Model>
struct constraint_check
{
virtual void failed(Model* x)
{
x->constraints();
}
};
}
template <class Model>
struct concept_check
: conditional<
concept_checking::has_constraints<Model>::value
, concept_checking::constraint_check<Model>
, concept_checking::concept_check_<Model>
>::type
{};
# else
template <class Model>
struct concept_check
: concept_checking::concept_check_<Model>
{};
# endif
# if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
//
// The iterator library sees some really strange errors unless we
// use partial specialization to extract the model type with
// msvc-7.1
//
template <class Model>
struct concept_check<void(*)(Model)>
: concept_check<Model>
{ };
# define BOOST_CONCEPT_ASSERT( ModelInParens ) \
enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \
sizeof(::boost::concept_check<void(*) ModelInParens>) \
}
# else
template <class Model>
concept_check<Model>
concept_check_(void(*)(Model));
# define BOOST_CONCEPT_ASSERT( ModelInParens ) \
enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \
sizeof(::boost::concept_check_((void(*) ModelInParens)0)) \
}
# endif
}
#endif // BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP

View File

@ -4,6 +4,10 @@
</head>
<body>
Automatic redirection failed, please go to
<a href="concept_check.htm">concept_check.htm</a>.
<a href="concept_check.htm">concept_check.htm</a>.&nbsp;<hr>
<p><EFBFBD> Copyright Beman Dawes, 2001</p>
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
</body>
</html>

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<explicit-failures-markup>
<!-- concept_check -->
<library name="concept_check">
<test name="class_concept_fail_expected">
<mark-failure>
<toolset name="cw-8.3*"/>
<note author="B. Dawes" refid="3"/>
</mark-failure>
</test>
<test name="class_concept_fail_expected">
<mark-failure>
<toolset name="borland-5*"/>
<toolset name="msvc-6.5*"/>
<toolset name="msvc-7.0"/>
<note author="Jeremy Siek"/>
</mark-failure>
</test>
<test name="stl_concept_check">
<mark-failure>
<toolset name="hp_cxx*"/>
<note author="Markus Schoepflin" date="09 Dec 2007">
This version of the Rogue Wave library fails to provide all
needed addition operators for the iterator type and the
difference type of std::deque.
</note>
</mark-failure>
</test>
</library>
</explicit-failures-markup>

16
meta/libraries.json Normal file
View File

@ -0,0 +1,16 @@
{
"key": "concept_check",
"name": "Concept Check",
"authors": [
"Jeremy Siek"
],
"description": "Tools for generic programming.",
"category": [
"Correctness",
"Generic"
],
"maintainers": [
"Jeremy Siek <jeremy.siek -at- gmail.com>"
],
"cxxstd": "03"
}

View File

@ -1,57 +1,55 @@
<HTML>
<!--
-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. We make no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
-->
<Head>
<Title>Programming With Concepts</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<BR Clear>
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000 -->
<!-- Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<h2><a name="programming-with-concepts">Programming with Concepts</a></h2>
<head>
<meta name="generator" content=
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" />
The process of deciding how to group requirements into concepts and
deciding which concepts to use in each algorithm is perhaps the most
difficult (yet most important) part of building a generic library.
A guiding principle to use during this process is one we
call the <i>requirement minimization principle</i>.
<title>Programming With Concepts</title>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
<link rel="stylesheet" href="../../rst.css" type="text/css" />
</head>
<p>
<b>Requirement Minimization Principle:</b> Minimize the requirements
on the input parameters of a component to increase its reusability.
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
"#FF0000">
<img src="../../boost.png" alt="C++ Boost" width="277" height=
"86" /><br clear="none" />
<p>
There is natural tension in this statement. By definition, the input
parameters must be used by the component in order for the component to
accomplish its task (by ``component'' we mean a function or class
template). The challenge then is to implement the component in such a
way that makes the fewest assumptions (the minimum requirements) about
the inputs while still accomplishing the task.
<h2><a name="programming-with-concepts" id=
"programming-with-concepts">Programming with Concepts</a></h2>
<p>
The traditional notions of <i>abstraction</i> tie in directly to the
idea of minimal requirements. The more abstract the input, the fewer
the requirements. Thus, concepts are simply the embodiment of generic
abstract data types in C++ template programming.
<p>The process of deciding how to group requirements into concepts and
deciding which concepts to use in each algorithm is perhaps the most
difficult (yet most important) part of building a generic library. A
guiding principle to use during this process is one we call the
<i>requirement minimization principle</i>.</p>
<p>
When designing the concepts for some problem domain it is important to
keep in mind their purpose, namely to express the requirements for the
input to the components. With respect to the requirement minimization
principle, this means we want to minimize concepts.
<p><b>Requirement Minimization Principle:</b> Minimize the requirements on
the input parameters of a component to increase its reusability.</p>
<!-- the following discussion does not match the Standard definition
<p>There is natural tension in this statement. By definition, the input
parameters must be used by the component in order for the component to
accomplish its task (by ``component'' we mean a function or class
template). The challenge then is to implement the component in such a way
that makes the fewest assumptions (the minimum requirements) about the
inputs while still accomplishing the task.</p>
<p>The traditional notions of <i>abstraction</i> tie in directly to the
idea of minimal requirements. The more abstract the input, the fewer the
requirements. Thus, concepts are simply the embodiment of generic abstract
data types in C++ template programming.</p>
<p>When designing the concepts for some problem domain it is important to
keep in mind their purpose, namely to express the requirements for the
input to the components. With respect to the requirement minimization
principle, this means we want to minimize concepts.
<!-- the following discussion does not match the Standard definition
of LessThanComparable and needs to be changed -Jeremy
<p>
@ -62,7 +60,7 @@ in the concept.
For example, the
<tt>std::stable_sort()</tt> function requires that the value type of
the iterator be <a
href="http://www.sgi.com/tech/stl/LessThanComparable.html">
href="http://www.boost.org/sgi/stl/LessThanComparable.html">
LessThanComparable</a>, which not only
includes <tt>operator&lt;()</tt>, but also <tt>operator&gt;()</tt>,
<tt>operator&lt;=()</tt>, and <tt>operator&gt;=()</tt>.
@ -70,25 +68,25 @@ It turns out that <tt>std::stable_sort()</tt> only uses
<tt>operator&lt;()</tt>. The question then arises: should
<tt>std::stable_sort()</tt> be specified in terms of the concept
<a
href="http://www.sgi.com/tech/stl/LessThanComparable.html">
href="http://www.boost.org/sgi/stl/LessThanComparable.html">
LessThanComparable</a> or in terms of a concept that only
requires <tt>operator&lt;()</tt>?
<p>
We remark first that the use of <a
href="http://www.sgi.com/tech/stl/LessThanComparable.html">
href="http://www.boost.org/sgi/stl/LessThanComparable.html">
LessThanComparable</a> does not really violate the requirement
minimization principle because all of the other operators can be
trivially implemented in terms of <tt>operator&lt;()</tt>. By
``trivial'' we mean one line of code and a constant run-time cost.
More fundamentally, however, the use of <a
href="http://www.sgi.com/tech/stl/LessThanComparable.html">
href="http://www.boost.org/sgi/stl/LessThanComparable.html">
LessThanComparable</a> does not violate the requirement minimization
principle because all of the comparison operators (<tt>&lt;</tt>,
<tt>></tt>, <tt><=</tt>, <tt>>=</tt>) are conceptually equivalent (in
a mathematical sense). Adding conceptually equivalent valid
expressions is not a violation of the requirement minimization
principle because no new semantics are being added --- only new
principle because no new semantics are being added === only new
syntax. The added syntax increases re-usability.
<p>
@ -100,49 +98,47 @@ implementation in places to use <tt>operator>()</tt> instead of
requirements are part of the public interface, such a change could
potentially break client code. If instead
<a
href="http://www.sgi.com/tech/stl/LessThanComparable.html">
href="http://www.boost.org/sgi/stl/LessThanComparable.html">
LessThanComparable</a> is given as the requirement for
<tt>std::stable_sort()</tt>, then the maintainer is given a reasonable
amount of flexibility within which to work.
-->
--></p>
<p>
Minimality in concepts is a property associated with the underlying
semantics of the problem domain being represented. In the problem
domain of basic containers, requiring traversal in a single direction
is a smaller requirement than requiring traversal in both directions
(hence the distinction between <a
href="http://www.sgi.com/tech/stl/ForwardIterator.html">
ForwardIterator</a> and
<a
href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">
BidirectionalIterator</a>). The semantic difference can be easily seen
in the difference between the set of concrete data structures that
have forward iterators versus the set that has bidirectional
iterators. For example, singly-linked lists would fall in the set of
data structures having forward iterators, but not bidirectional
iterators. In addition, the set of algorithms that one can implement
using only forward iterators is quite different than the set that can
be implemented with bidirectional iterators. Because of this, it is
important to factor families of requirements into rather fine-grained
concepts. For example, the requirements for iterators are factored
into the six STL iterator concepts (trivial, output, input, forward,
bidirectional, and random access).
<p>Minimality in concepts is a property associated with the underlying
semantics of the problem domain being represented. In the problem domain of
basic containers, requiring traversal in a single direction is a smaller
requirement than requiring traversal in both directions (hence the
distinction between <a href=
"http://www.boost.org/sgi/stl/ForwardIterator.html">ForwardIterator</a> and
<a href=
"http://www.boost.org/sgi/stl/BidirectionalIterator.html">BidirectionalIterator</a>).
The semantic difference can be easily seen in the difference between the
set of concrete data structures that have forward iterators versus the set
that has bidirectional iterators. For example, singly-linked lists would
fall in the set of data structures having forward iterators, but not
bidirectional iterators. In addition, the set of algorithms that one can
implement using only forward iterators is quite different than the set that
can be implemented with bidirectional iterators. Because of this, it is
important to factor families of requirements into rather fine-grained
concepts. For example, the requirements for iterators are factored into the
six STL iterator concepts (trivial, output, input, forward, bidirectional,
and random access).</p>
<p>
<a href="./implementation.htm">Next: Implementation</a><br>
<a href="./concept_covering.htm">Prev: Concept Covering and Archetypes</a>
<p><a href="./implementation.htm">Next: Implementation</a><br />
<a href="./concept_covering.htm">Prev: Concept Covering and
Archetypes</a><br /></p>
<hr />
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
</TD></TR></TABLE>
<table>
<tr valign="top">
<td nowrap="nowrap">Copyright &copy; 2000</td>
</BODY>
</HTML>
<td><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
"mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>),
2007 <a href="mailto:dave@boost-consulting.com">David Abrahams</a>.
</tr>
</table>
</body>
</html>

View File

@ -1,314 +1,418 @@
<HTML>
<!--
-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. We make no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
-->
<Head>
<Title>Boost Concept Checking Reference</Title>
</Head>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<BR Clear>
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000 -->
<!-- Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<h2><a name="reference">Reference</a></h2>
<head>
<meta name="generator" content=
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="../../rst.css" type="text/css" />
<OL>
<LI><a href="#functions">Functions</a></LI>
<LI><a href="#macros">Macros</a></LI>
<LI><a href="#basic-concepts">Basic Concept Checking Classes</a></LI>
<LI><a href="#iterator-concepts">Iterator Concept Checking Classes</a></LI>
<LI><a href="#function-object-concepts">Function Object Concept Checking Classes</a></LI>
<LI><a href="#container-concepts">Container Concept Checking Classes</a></LI>
<LI><a href="#basic-archetype">Basic Archetype Classes</a></LI>
<LI><a href="#iterator-archetype">Iterator Archetype Classes</a></LI>
<LI><a href="#function-object-archetype">Function Object Archetype Classes</a></LI>
<LI><a href="#container-archetype">Container Archetype Classes</a></LI>
</OL>
<title>Boost Concept Checking Reference</title>
</head>
<h3><a name="functions">Functions</a></h3>
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
"#FF0000">
<img src="../../boost.png" alt="C++ Boost" width="277" height=
"86" /><br clear="none" />
<pre>
template &lt;class Concept&gt;
void function_requires();
<h2><a name="reference" id="reference">Reference</a></h2>
<ol>
<li><a href="#macros">Macros</a></li>
<li><a href="#basic-concepts">Basic Concept Checking Classes</a></li>
<li><a href="#iterator-concepts">Iterator Concept Checking
Classes</a></li>
<li><a href="#function-object-concepts">Function Object Concept Checking
Classes</a></li>
<li><a href="#container-concepts">Container Concept Checking
Classes</a></li>
<li><a href="#basic-archetype">Basic Archetype Classes</a></li>
<li><a href="#iterator-archetype">Iterator Archetype Classes</a></li>
<li><a href="#function-object-archetype">Function Object Archetype
Classes</a></li>
<li><a href="#container-archetype">Container Archetype Classes</a></li>
<li><a href="#deprecated-functions">Deprecated Functions</a></li>
<li><a href="#deprecated-macros">Deprecated Macros</a></li>
<li><a href="#deprecated-concept-checking-classes">Deprecated Concept
Checking Classes</a></li>
</ol>
<h3><a name="macros" id="macros">Macros</a></h3>
<pre>
#include "boost/concept/assert.hpp"
BOOST_CONCEPT_ASSERT((<em>concept checking class template specialization</em>));
</pre>
<h3><a name="macros">Macros</a></h3>
<p><strong>Effects:</strong> causes a compilation failure if the concept is
not satisfied.<br />
<strong>Note:</strong> this macro can be used at global, class, or function
scope.</p>
<pre>
// Apply concept checks in class definitions.
BOOST_CLASS_REQUIRE(<i>type</i>, <i>namespace-of-concept</i>, <i>concept</i>);
BOOST_CLASS_REQUIRE2(<i>type1</i>, <i>type2</i>, <i>namespace-of-concept</i>, <i>concept</i>);
BOOST_CLASS_REQUIRE3(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>namespace-of-concept</i>, <i>concept</i>);
BOOST_CLASS_REQUIRE4(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>type4</i>, <i>namespace-of-concept</i>, <i>concept</i>);
<pre>
#include "boost/concept/requires.hpp"
<font color="gray">template &lt;<em>template parameters</em>&gt;</font>
BOOST_CONCEPT_REQUIRES(
((<em>concept checking class template specialization<sub>1</sub></em>))
((<em>concept checking class template specialization<sub>2</sub></em>))…
((<em>concept checking class template specialization<sub>n</sub></em>))<strong>,</strong>
(<em>function return type</em>)
) <font color="gray"><em>function_template_name</em>(…<em>function parameters</em>…)</font>
</pre>
Deprecated macros:
<p><strong>Effects:</strong> causes a compilation failure if the
given concepts are not satisfied.<br />
<strong>Note:</strong> this macro is intended to be used in place of
a function template's return type.</p>
<pre>
// Apply concept checks in class definitions.
BOOST_CLASS_REQUIRES(<i>type</i>, <i>concept</i>);
BOOST_CLASS_REQUIRES2(<i>type1</i>, <i>type2</i>, <i>concept</i>);
BOOST_CLASS_REQUIRES3(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>concept</i>);
BOOST_CLASS_REQUIRES4(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>type4</i>, <i>concept</i>);
<h3><a name="basic-concepts" id="basic-concepts">Basic Concept Checking
Classes</a></h3>
<pre>
#include "boost/concept_check.hpp"
template &lt;class T&gt;
struct Integer; // Is T a built-in integer type?
template &lt;class T&gt;
struct SignedInteger; // Is T a built-in signed integer type?
template &lt;class T&gt;
struct UnsignedInteger; // Is T a built-in unsigned integer type?
template &lt;class X, class Y&gt;
struct Convertible; // Is X convertible to Y?
template &lt;class T&gt;
struct <a href=
"../utility/Assignable.html">Assignable</a>; // Standard ref 23.1
template &lt;class T&gt;
struct SGI<a href=
"http://www.boost.org/sgi/stl/Assignable.html">Assignable</a>;
template &lt;class T&gt;
struct <a href=
"http://www.boost.org/sgi/stl/DefaultConstructible.html">DefaultConstructible</a>;
template &lt;class T&gt;
struct <a href=
"../utility/CopyConstructible.html">CopyConstructible</a>; // Standard ref 20.1.3
template &lt;class T&gt;
struct <a href=
"http://www.boost.org/sgi/stl/EqualityComparable.html">EqualityComparable</a>; // Standard ref 20.1.1
template &lt;class T&gt;
struct <a href=
"../utility/LessThanComparable.html">LessThanComparable</a>; // Standard ref 20.1.2
template &lt;class T&gt;
struct Comparable; // The SGI STL <a href=
"http://www.boost.org/sgi/stl/LessThanComparable.html">LessThanComparable</a> concept
</pre>
<h3><a name="basic-concepts">Basic Concept Checking Classes</a></h3>
<h3><a name="iterator-concepts" id="iterator-concepts">Iterator Concept
Checking Classes</a></h3>
<pre>
template &lt;class Iter&gt;
struct <a href=
"http://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a>; // Standard ref 24.1.1 Table 72
<pre>
template &lt;class T&gt;
struct IntegerConcept; // Is T a built-in integer type?
template &lt;class Iter, class T&gt;
struct <a href=
"http://www.boost.org/sgi/stl/OutputIterator.html">OutputIterator</a>; // Standard ref 24.1.2 Table 73
template &lt;class T&gt;
struct SignedIntegerConcept; // Is T a built-in signed integer type?
template &lt;class Iter&gt;
struct <a href=
"http://www.boost.org/sgi/stl/ForwardIterator.html">ForwardIterator</a>; // Standard ref 24.1.3 Table 74
template &lt;class T&gt;
struct UnsignedIntegerConcept; // Is T a built-in unsigned integer type?
template &lt;class Iter&gt;
struct Mutable_ForwardIterator;
template &lt;class X, class Y&gt;
struct ConvertibleConcept; // Is X convertible to Y?
template &lt;class Iter&gt;
struct <a href=
"http://www.boost.org/sgi/stl/BidirectionalIterator.html">BidirectionalIterator</a>; // Standard ref 24.1.4 Table 75
template &lt;class T&gt;
struct <a href="../utility/Assignable.html">Assignable</a>Concept; // Standard ref 23.1
template &lt;class Iter&gt;
struct Mutable_BidirectionalIterator;
template &lt;class T&gt;
struct SGI<a href="http://www.sgi.com/tech/stl/Assignable.html">Assignable</a>Concept;
template &lt;class Iter&gt;
struct <a href=
"http://www.boost.org/sgi/stl/RandomAccessIterator.html">RandomAccessIterator</a>; // Standard ref 24.1.5 Table 76
template &lt;class T&gt;
struct <a
href="http://www.sgi.com/tech/stl/DefaultConstructible.html">DefaultConstructible</a>Concept;
template &lt;class T&gt;
struct <a href="../utility/CopyConstructible.html">CopyConstructible</a>Concept; // Standard ref 20.1.3
template &lt;class T&gt;
struct <a href="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a>Concept; // Standard ref 20.1.1
template &lt;class T&gt;
struct <a href="../utility/LessThanComparable.html">LessThanComparable</a>Concept; // Standard ref 20.1.2
template &lt;class T&gt;
struct ComparableConcept; // The SGI STL <a href="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</a> concept
template &lt;class Iter&gt;
struct Mutable_RandomAccessIterator;
</pre>
<h3><a name="iterator-concepts">Iterator Concept Checking Classes</a></h3>
<h3><a name="function-object-concepts" id=
"function-object-concepts">Function Object Concept Checking
Classes</a></h3>
<pre>
#include "boost/concept_check.hpp"
<pre>
template &lt;class Iter&gt;
struct <a href="http://www.sgi.com/tech/stl/trivial.html">TrivialIterator</a>Concept;
template &lt;class Func, class Return&gt;
struct <a href="http://www.boost.org/sgi/stl/Generator.html">Generator</a>;
template &lt;class Iter&gt;
struct Mutable_TrivialIteratorConcept;
template &lt;class Func, class Return, class Arg&gt;
struct <a href=
"http://www.boost.org/sgi/stl/UnaryFunction.html">UnaryFunction</a>;
template &lt;class Iter&gt;
struct <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>Concept; // Standard ref 24.1.1 Table 72
template &lt;class Func, class Return, class First, class Second&gt;
struct <a href=
"http://www.boost.org/sgi/stl/BinaryFunction.html">BinaryFunction</a>;
template &lt;class Iter, class T&gt;
struct <a href="http://www.sgi.com/tech/stl/OutputIterator.html">OutputIterator</a>Concept; // Standard ref 24.1.2 Table 73
template &lt;class Func, class Arg&gt;
struct Unary<a href=
"http://www.boost.org/sgi/stl/Predicate.html">Predicate</a>;
template &lt;class Iter&gt;
struct <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>Concept; // Standard ref 24.1.3 Table 74
template &lt;class Func, class First, class Second&gt;
struct <a href=
"http://www.boost.org/sgi/stl/BinaryPredicate.html">BinaryPredicate</a>;
template &lt;class Iter&gt;
struct Mutable_ForwardIteratorConcept;
template &lt;class Func, class First, class Second&gt;
struct Const_BinaryPredicate;
template &lt;class Iter&gt;
struct <a href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>Concept; // Standard ref 24.1.4 Table 75
template &lt;class Func, class Return&gt;
struct <a href=
"http://www.boost.org/sgi/stl/AdaptableGenerator.html">AdaptableGenerator</a>;
template &lt;class Iter&gt;
struct Mutable_BidirectionalIteratorConcept;
template &lt;class Func, class Return, class Arg&gt;
struct <a href=
"http://www.boost.org/sgi/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>;
template &lt;class Iter&gt;
struct <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>Concept; // Standard ref 24.1.5 Table 76
template &lt;class Func, class First, class Second&gt;
struct <a href=
"http://www.boost.org/sgi/stl/AdaptableBinaryFunction.html">AdaptableBinaryFunction</a>;
template &lt;class Iter&gt;
struct Mutable_RandomAccessIteratorConcept;
template &lt;class Func, class Arg&gt;
struct <a href=
"http://www.boost.org/sgi/stl/AdaptablePredicate.html">AdaptablePredicate</a>;
template &lt;class Func, class First, class Second&gt;
struct <a href=
"http://www.boost.org/sgi/stl/AdaptableBinaryPredicate.html">AdaptableBinaryPredicate</a>;
</pre>
<h3><a name="function-object-concepts">Function Object Concept Checking Classes</a></h3>
<h3><a name="container-concepts" id="container-concepts">Container Concept
Checking Classes</a></h3>
<pre>
#include "boost/concept_check.hpp"
<pre>
template &lt;class Func, class Return&gt;
struct <a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a>Concept;
template &lt;class C&gt;
struct <a href=
"http://www.boost.org/sgi/stl/Container.html">Container</a>; // Standard ref 23.1 Table 65
template &lt;class Func, class Return, class Arg&gt;
struct <a href="http://www.sgi.com/tech/stl/UnaryFunction.html">UnaryFunction</a>Concept;
template &lt;class C&gt;
struct Mutable_Container;
template &lt;class Func, class Return, class First, class Second&gt;
struct <a href="http://www.sgi.com/tech/stl/BinaryFunction.html">BinaryFunction</a>Concept;
template &lt;class C&gt;
struct <a href=
"http://www.boost.org/sgi/stl/ForwardContainer.html">ForwardContainer</a>;
template &lt;class Func, class Arg&gt;
struct Unary<a href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</a>Concept;
template &lt;class C&gt;
struct Mutable_ForwardContainer;
template &lt;class Func, class First, class Second&gt;
struct <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>Concept;
template &lt;class C&gt;
struct <a href=
"http://www.boost.org/sgi/stl/ReversibleContainer.html">ReversibleContainer</a>; // Standard ref 23.1 Table 66
template &lt;class Func, class First, class Second&gt;
struct Const_BinaryPredicateConcept;
template &lt;class C&gt;
struct Mutable_ReversibleContainer;
template &lt;class Func, class Return&gt;
struct <a href="http://www.sgi.com/tech/stl/AdaptableGenerator.html">AdaptableGenerator</a>Concept;
template &lt;class C&gt;
struct <a href=
"http://www.boost.org/sgi/stl/RandomAccessContainer.html">RandomAccessContainer</a>;
template &lt;class Func, class Return, class Arg&gt;
struct <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>Concept;
template &lt;class C&gt;
struct Mutable_RandomAccessContainer;
template &lt;class Func, class First, class Second&gt;
struct <a href="http://www.sgi.com/tech/stl/AdaptableBinaryFunction.html">AdaptableBinaryFunction</a>Concept;
template &lt;class C&gt;
struct <a href=
"http://www.boost.org/sgi/stl/Sequence.html">Sequence</a>; // Standard ref 23.1.1
template &lt;class Func, class Arg&gt;
struct <a href="http://www.sgi.com/tech/stl/AdaptablePredicate.html">AdaptablePredicate</a>Concept;
template &lt;class C&gt;
struct <a href=
"http://www.boost.org/sgi/stl/FrontInsertionSequence.html">FrontInsertionSequence</a>;
template &lt;class Func, class First, class Second&gt;
struct <a href="http://www.sgi.com/tech/stl/AdaptableBinaryPredicate.html">AdaptableBinaryPredicate</a>Concept;
template &lt;class C&gt;
struct <a href=
"http://www.boost.org/sgi/stl/BackInsertionSequence.html">BackInsertionSequence</a>;
template &lt;class C&gt;
struct <a href=
"http://www.boost.org/sgi/stl/AssociativeContainer.html">AssociativeContainer</a>; // Standard ref 23.1.2 Table 69
template &lt;class C&gt;
struct <a href=
"http://www.boost.org/sgi/stl/UniqueAssociativeContainer.html">UniqueAssociativeContainer</a>;
template &lt;class C&gt;
struct <a href=
"http://www.boost.org/sgi/stl/MultipleAssociativeContainer.html">MultipleAssociativeContainer</a>;
template &lt;class C&gt;
struct <a href=
"http://www.boost.org/sgi/stl/SimpleAssociativeContainer.html">SimpleAssociativeContainer</a>;
template &lt;class C&gt;
struct <a href=
"http://www.boost.org/sgi/stl/PairAssociativeContainer.html">PairAssociativeContainer</a>;
template &lt;class C&gt;
struct <a href=
"http://www.boost.org/sgi/stl/SortedAssociativeContainer.html">SortedAssociativeContainer</a>;
template &lt;class C&gt;
struct <a href=
"../utility/Collection.html">Collection</a>;
</pre>
<h3><a name="container-concepts">Container Concept Checking Classes</a></h3>
<h3><a name="basic-archetype" id="basic-archetype">Basic Archetype
Classes</a></h3>
<pre>
#include "boost/concept_archetype.hpp"
<pre>
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/Container.html">Container</a>Concept; // Standard ref 23.1 Table 65
template &lt;class T = int&gt;
class null_archetype; // A type that models no concepts.
template &lt;class C&gt;
struct Mutable_ContainerConcept;
template &lt;class Base = null_archetype&gt;
class default_constructible_archetype;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/ForwardContainer.html">ForwardContainer</a>Concept;
template &lt;class Base = null_archetype&gt;
class assignable_archetype;
template &lt;class C&gt;
struct Mutable_ForwardContainerConcept;
template &lt;class Base = null_archetype&gt;
class copy_constructible_archetype;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/ReversibleContainer.html">ReversibleContainer</a>Concept; // Standard ref 23.1 Table 66
template &lt;class Base = null_archetype&gt;
class equality_comparable_archetype;
template &lt;class C&gt;
struct Mutable_ReversibleContainerConcept;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/RandomAccessContainer.html">RandomAccessContainer</a>Concept;
template &lt;class C&gt;
struct Mutable_RandomAccessContainerConcept;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/SequenceContainer.html">Sequence</a>Concept; // Standard ref 23.1.1
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/FrontInsertionSequence.html">FrontInsertionSequence</a>Concept;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/BackInsertionSequence.html">BackInsertionSequence</a>Concept;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/Associative.html">AssociativeContainer</a>Concept; // Standard ref 23.1.2 Table 69
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html">UniqueAssociativeContainer</a>Concept;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/MultipleAssociativeContainer.html">MultipleAssociativeContainer</a>Concept;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/SimpleAssociativeContainer.html">SimpleAssociativeContainer</a>Concept;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/PairAssociativeContainer.html">PairAssociativeContainer</a>Concept;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/SortedAssociativeContainer.html">SortedAssociativeContainer</a>Concept;
template &lt;class T, class Base = null_archetype&gt;
class convertible_to_archetype;
</pre>
<h3><a name="iterator-archetype" id="iterator-archetype">Iterator Archetype
Classes</a></h3>
<pre>
#include "boost/concept_archetype.hpp"
<h3><a name="basic-archetype">Basic Archetype Classes</a></h3>
template &lt;class ValueType&gt;
class trivial_iterator_archetype;
<pre>
template &lt;class T = int&gt;
class null_archetype; // A type that models no concepts.
template &lt;class ValueType&gt;
class mutable_trivial_iterator_archetype;
template &lt;class Base = null_archetype&gt;
class default_constructible_archetype;
template &lt;class ValueType&gt;
class input_iterator_archetype;
template &lt;class Base = null_archetype&gt;
class assignable_archetype;
template &lt;class ValueType&gt;
class forward_iterator_archetype;
template &lt;class Base = null_archetype&gt;
class copy_constructible_archetype;
template &lt;class ValueType&gt;
class bidirectional_iterator_archetype;
template &lt;class Base = null_archetype&gt;
class equality_comparable_archetype;
template &lt;class T, class Base = null_archetype&gt;
class convertible_to_archetype;
template &lt;class ValueType&gt;
class random_access_iterator_archetype;
</pre>
<h3><a name="iterator-archetype">Iterator Archetype Classes</a></h3>
<h3><a name="function-object-archetype" id=
"function-object-archetype">Function Object Archetype Classes</a></h3>
<pre>
#include "boost/concept_archetype.hpp"
<pre>
template &lt;class ValueType&gt;
class trivial_iterator_archetype;
template &lt;class Arg, class Return&gt;
class unary_function_archetype;
template &lt;class ValueType&gt;
class mutable_trivial_iterator_archetype;
template &lt;class Arg1, class Arg2, class Return&gt;
class binary_function_archetype;
template &lt;class ValueType&gt;
class input_iterator_archetype;
template &lt;class ValueType&gt;
class forward_iterator_archetype;
template &lt;class ValueType&gt;
class bidirectional_iterator_archetype;
template &lt;class ValueType&gt;
class random_access_iterator_archetype;
template &lt;class Arg&gt;
class predicate_archetype;
template &lt;class Arg1, class Arg2&gt;
class binary_predicate_archetype;
</pre>
<h3><a name="function-object-archetype">Function Object Archetype Classes</a></h3>
<pre>
template &lt;class Arg, class Return&gt;
class unary_function_archetype;
template &lt;class Arg1, class Arg2, class Return&gt;
class binary_function_archetype;
template &lt;class Arg&gt;
class predicate_archetype;
template &lt;class Arg1, class Arg2&gt;
class binary_predicate_archetype;
</pre>
<h3><a name="container-archetype">Container Archetype Classes</a></h3>
<pre>
<h3><a name="container-archetype" id="container-archetype">Container
Archetype Classes</a></h3>
<pre>
UNDER CONSTRUCTION
</pre>
<p>
<a href="./concept_check.htm">Back to Introduction</a>
<br>
<a href="./implementation.htm">Prev: Implementation</a>
<h3><a name="deprecated-functions" id="deprecated-functions">Deprecated
Functions</a></h3>
<pre>
#include "boost/concept_check.hpp"
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
</TD></TR></TABLE>
template &lt;class Concept&gt;
void function_requires();
</pre>
</BODY>
</HTML>
<p><code>function_requires()</code> has been deprecated in favor of <code>BOOST_CONCEPT_ASSERT</code>.
This means that <del><code>function_requires< Concept<Type> >();</code></del>
becomes <code>BOOST_CONCEPT_ASSERT((Concept<Type>));</code>
(don't forget to <code>#include &quot;boost/concept/assert.hpp&quot;</code>).
<h3><a name="deprecated-macros" id="deprecated-macros">Deprecated
Macros</a></h3>
<pre>
#include "boost/concept_check.hpp"
// Apply concept checks in class definitions.
BOOST_CLASS_REQUIRE(<i>type</i>, <i>namespace-of-concept</i>, <i>concept</i>);
BOOST_CLASS_REQUIRE2(<i>type1</i>, <i>type2</i>, <i>namespace-of-concept</i>, <i>concept</i>);
BOOST_CLASS_REQUIRE3(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>namespace-of-concept</i>, <i>concept</i>);
BOOST_CLASS_REQUIRE4(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>type4</i>, <i>namespace-of-concept</i>, <i>concept</i>);
// Apply concept checks in class definitions.
BOOST_CLASS_REQUIRES(<i>type</i>, <i>concept</i>);
BOOST_CLASS_REQUIRES2(<i>type1</i>, <i>type2</i>, <i>concept</i>);
BOOST_CLASS_REQUIRES3(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>concept</i>);
BOOST_CLASS_REQUIRES4(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>type4</i>, <i>concept</i>);
</pre>
<h3><a name="deprecated-concept-checking-classes" id=
"deprecated-concept-checking-classes">Deprecated Concept Checking
Classes</a></h3>
<p>For each of the concepts documented here, the library includes an
identical concept checking class whose name ends in
<code>Concept</code>” For example, in
addition to <code>RandomAccessIterator</code>, the library defines a
<code>RandomAccessIteratorConcept</code> class template.</p>
<p><a href="./concept_check.htm">Back to Introduction</a><br />
<a href="./implementation.htm">Prev: Implementation</a><br /></p>
<hr />
<table>
<tr valign="top">
<td nowrap="nowrap">Copyright &copy; 2000</td>
<td><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
"mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>), 2007
<a href="mailto:dave@boost-consulting.com">David Abrahams</a>.</td>
</tr>
</table>
</body>
</html>

View File

@ -1,93 +0,0 @@
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
//
// This file checks to see if various standard container
// implementations live up to requirements specified in the C++
// standard. As many implementations do not live to the requirements,
// it is not uncommon for this file to fail to compile. The
// BOOST_HIDE_EXPECTED_ERRORS macro is provided here if you want to
// see as much of this file compile as possible.
//
#include <boost/concept_check.hpp>
#include <iterator>
#include <set>
#include <map>
#include <vector>
#include <list>
#include <deque>
#ifndef BOOST_NO_SLIST
#include <slist>
#endif
// Define this macro if you want to hide the expected error, that is,
// error in the various C++ standard library implementations.
//
//#define BOOST_HIDE_EXPECTED_ERRORS
int
main()
{
using namespace boost;
#if defined(_ITERATOR_) && defined(BOOST_HIDE_EXPECTED_ERRORS)
// VC++ STL implementation is not standard conformant and
// fails to pass these concept checks
#else
typedef std::vector<int> Vector;
typedef std::deque<int> Deque;
typedef std::list<int> List;
// VC++ missing pointer and const_pointer typedefs
function_requires< Mutable_RandomAccessContainerConcept<Vector> >();
function_requires< BackInsertionSequenceConcept<Vector> >();
#if !(defined(__GNUC__) && defined(BOOST_HIDE_EXPECTED_ERRORS))
#if !(defined(__sgi) && defined(BOOST_HIDE_EXPECTED_ERRORS))
// old deque iterator missing n + iter operation
function_requires< Mutable_RandomAccessContainerConcept<Deque> >();
#endif
// warnings about signed and unsigned in old deque version
function_requires< FrontInsertionSequenceConcept<Deque> >();
function_requires< BackInsertionSequenceConcept<Deque> >();
#endif
// VC++ missing pointer and const_pointer typedefs
function_requires< Mutable_ReversibleContainerConcept<List> >();
function_requires< FrontInsertionSequenceConcept<List> >();
function_requires< BackInsertionSequenceConcept<List> >();
#ifndef BOOST_NO_SLIST
typedef BOOST_STD_EXTENSION_NAMESPACE::slist<int> SList;
function_requires< FrontInsertionSequenceConcept<SList> >();
#endif
typedef std::set<int> Set;
typedef std::multiset<int> MultiSet;
typedef std::map<int,int> Map;
typedef std::multimap<int,int> MultiMap;
function_requires< SortedAssociativeContainerConcept<Set> >();
function_requires< SimpleAssociativeContainerConcept<Set> >();
function_requires< UniqueAssociativeContainerConcept<Set> >();
function_requires< SortedAssociativeContainerConcept<MultiSet> >();
function_requires< SimpleAssociativeContainerConcept<MultiSet> >();
function_requires< MultipleAssociativeContainerConcept<MultiSet> >();
function_requires< SortedAssociativeContainerConcept<Map> >();
function_requires< UniqueAssociativeContainerConcept<Map> >();
function_requires< PairAssociativeContainerConcept<Map> >();
function_requires< SortedAssociativeContainerConcept<MultiMap> >();
function_requires< MultipleAssociativeContainerConcept<MultiMap> >();
function_requires< PairAssociativeContainerConcept<MultiMap> >();
#endif
return 0;
}

View File

@ -1,90 +0,0 @@
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
//
// This file checks to see if various standard container
// implementations live up to requirements specified in the C++
// standard. As many implementations do not live to the requirements,
// it is not uncommon for this file to fail to compile. The
// BOOST_HIDE_EXPECTED_ERRORS macro is provided here if you want to
// see as much of this file compile as possible.
//
#include <boost/pending/concept_checks.hpp>
#include <iterator>
#include <set>
#include <map>
#include <vector>
#include <list>
#include <deque>
#ifndef BOOST_NO_SLIST
#include <slist>
#endif
//#define BOOST_HIDE_EXPECTED_ERRORS
int
main()
{
using namespace boost;
#if defined(_ITERATOR_) && defined(BOOST_HIDE_EXPECTED_ERRORS)
// VC++ STL implementation is not standard conformant and
// fails to pass these concept checks
#else
typedef std::vector<int> Vector;
typedef std::deque<int> Deque;
typedef std::list<int> List;
// VC++ missing pointer and const_pointer typedefs
function_requires< Mutable_RandomAccessContainerConcept<Vector> >();
function_requires< BackInsertionSequenceConcept<Vector> >();
#if !(defined(__GNUC__) && defined(BOOST_HIDE_EXPECTED_ERRORS))
#if !(defined(__sgi) && defined(BOOST_HIDE_EXPECTED_ERRORS))
// old deque iterator missing n + iter operation
function_requires< Mutable_RandomAccessContainerConcept<Deque> >();
#endif
// warnings about signed and unsigned in old deque version
function_requires< FrontInsertionSequenceConcept<Deque> >();
function_requires< BackInsertionSequenceConcept<Deque> >();
#endif
// VC++ missing pointer and const_pointer typedefs
function_requires< Mutable_ReversibleContainerConcept<List> >();
function_requires< FrontInsertionSequenceConcept<List> >();
function_requires< BackInsertionSequenceConcept<List> >();
#ifndef BOOST_NO_SLIST
typedef std::slist<int> SList;
function_requires< FrontInsertionSequenceConcept<SList> >();
#endif
typedef std::set<int> Set;
typedef std::multiset<int> MultiSet;
typedef std::map<int,int> Map;
typedef std::multimap<int,int> MultiMap;
function_requires< SortedAssociativeContainerConcept<Set> >();
function_requires< SimpleAssociativeContainerConcept<Set> >();
function_requires< UniqueAssociativeContainerConcept<Set> >();
function_requires< SortedAssociativeContainerConcept<MultiSet> >();
function_requires< SimpleAssociativeContainerConcept<MultiSet> >();
function_requires< MultipleAssociativeContainerConcept<MultiSet> >();
function_requires< SortedAssociativeContainerConcept<Map> >();
function_requires< UniqueAssociativeContainerConcept<Map> >();
function_requires< PairAssociativeContainerConcept<Map> >();
function_requires< SortedAssociativeContainerConcept<MultiMap> >();
function_requires< MultipleAssociativeContainerConcept<MultiMap> >();
function_requires< PairAssociativeContainerConcept<MultiMap> >();
#endif
return 0;
}

25
test/Jamfile.v2 Normal file
View File

@ -0,0 +1,25 @@
# Copyright David Abrahams, Jeremy Siek, Vladimir Prus
# 2006. Distributed under the Boost Software License, Version
# 1.0. (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import testing ;
test-suite concept_check
: [ link stl_concept_covering.cpp ]
[ run stl_concept_check.cpp ]
[ run concept_check_test.cpp ]
[ run class_concept_check_test.cpp ]
[ compile-fail concept_check_fail_expected.cpp ]
[ compile-fail class_concept_fail_expected.cpp ]
[ run where.cpp ]
[ compile-fail where_fail.cpp ]
[ compile-fail usage_fail.cpp ]
# Backward compatibility tests
[ run old_concept_pass.cpp ]
[ compile-fail function_requires_fail.cpp ]
[ compile-fail old_concept_function_fail.cpp ]
[ compile-fail old_concept_class_fail.cpp ]
;

View File

@ -0,0 +1,34 @@
// (C) Copyright Jeremy Siek 2000.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/concept_check.hpp>
/*
This file verifies that the BOOST_CLASS_REQUIRE macro of the Boost
Concept Checking Library does not cause errors when it is not suppose
to.
*/
struct foo { bool operator()(int) { return true; } };
struct bar { bool operator()(int, char) { return true; } };
class class_requires_test
{
BOOST_CONCEPT_ASSERT((boost::EqualityComparable<int>));
typedef int* int_ptr; typedef const int* const_int_ptr;
BOOST_CONCEPT_ASSERT((boost::EqualOp<int_ptr,const_int_ptr>));
BOOST_CONCEPT_ASSERT((boost::UnaryFunction<foo,bool,int>));
BOOST_CONCEPT_ASSERT((boost::BinaryFunction<bar,bool,int,char>));
};
int
main()
{
class_requires_test x;
boost::ignore_unused_variable_warning(x);
return 0;
}

View File

@ -0,0 +1,32 @@
// (C) Copyright Jeremy Siek, David Abrahams 2000-2006.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Change Log:
// 20 Jan 2001 - Added warning suppression (David Abrahams)
#include <boost/concept_check.hpp>
/*
This file verifies that class_requires of the Boost Concept Checking
Library catches errors when it is supposed to.
*/
struct foo { };
template <class T>
class class_requires_test
{
BOOST_CONCEPT_ASSERT((boost::EqualityComparable<foo>));
};
int
main()
{
class_requires_test<int> x;
(void)x; // suppress unused variable warning
return 0;
}

View File

@ -0,0 +1,26 @@
// (C) Copyright Jeremy Siek, David Abrahams 2000-2006.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifdef NDEBUG
# undef NDEBUG
#endif
#include <boost/concept_check.hpp>
/*
This file verifies that BOOST_CONCEPT_ASSERT catches errors in
function context.
*/
struct foo { };
int
main()
{
BOOST_CONCEPT_ASSERT((boost::EqualityComparable<foo>));
return 0;
}

View File

@ -1,8 +1,7 @@
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
// (C) Copyright Jeremy Siek 2000.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/concept_check.hpp>
#include <boost/concept_archetype.hpp>
@ -26,76 +25,76 @@ main()
// Basic Concepts
{
typedef default_constructible_archetype<> foo;
function_requires< DefaultConstructibleConcept<foo> >();
function_requires< DefaultConstructible<foo> >();
}
{
typedef assignable_archetype<> foo;
function_requires< AssignableConcept<foo> >();
function_requires< Assignable<foo> >();
}
{
typedef copy_constructible_archetype<> foo;
function_requires< CopyConstructibleConcept<foo> >();
function_requires< CopyConstructible<foo> >();
}
{
typedef sgi_assignable_archetype<> foo;
function_requires< SGIAssignableConcept<foo> >();
function_requires< SGIAssignable<foo> >();
}
{
typedef copy_constructible_archetype<> foo;
typedef convertible_to_archetype<foo> convertible_to_foo;
function_requires< ConvertibleConcept<convertible_to_foo, foo> >();
function_requires< Convertible<convertible_to_foo, foo> >();
}
{
function_requires< ConvertibleConcept<boolean_archetype, bool> >();
function_requires< Convertible<boolean_archetype, bool> >();
}
{
typedef equality_comparable_archetype<> foo;
function_requires< EqualityComparableConcept<foo> >();
function_requires< EqualityComparable<foo> >();
}
{
typedef less_than_comparable_archetype<> foo;
function_requires< LessThanComparableConcept<foo> >();
function_requires< LessThanComparable<foo> >();
}
{
typedef comparable_archetype<> foo;
function_requires< ComparableConcept<foo> >();
function_requires< Comparable<foo> >();
}
{
typedef equal_op_first_archetype<> First;
typedef equal_op_second_archetype<> Second;
function_requires< EqualOpConcept<First, Second> >();
function_requires< EqualOp<First, Second> >();
}
{
typedef not_equal_op_first_archetype<> First;
typedef not_equal_op_second_archetype<> Second;
function_requires< NotEqualOpConcept<First, Second> >();
function_requires< NotEqualOp<First, Second> >();
}
{
typedef less_than_op_first_archetype<> First;
typedef less_than_op_second_archetype<> Second;
function_requires< LessThanOpConcept<First, Second> >();
function_requires< LessThanOp<First, Second> >();
}
{
typedef less_equal_op_first_archetype<> First;
typedef less_equal_op_second_archetype<> Second;
function_requires< LessEqualOpConcept<First, Second> >();
function_requires< LessEqualOp<First, Second> >();
}
{
typedef greater_than_op_first_archetype<> First;
typedef greater_than_op_second_archetype<> Second;
function_requires< GreaterThanOpConcept<First, Second> >();
function_requires< GreaterThanOp<First, Second> >();
}
{
typedef greater_equal_op_first_archetype<> First;
typedef greater_equal_op_second_archetype<> Second;
function_requires< GreaterEqualOpConcept<First, Second> >();
function_requires< GreaterEqualOp<First, Second> >();
}
{
typedef copy_constructible_archetype<> Return;
typedef plus_op_first_archetype<Return> First;
typedef plus_op_second_archetype<Return> Second;
function_requires< PlusOpConcept<Return, First, Second> >();
function_requires< PlusOp<Return, First, Second> >();
}
//===========================================================================
@ -103,73 +102,70 @@ main()
{
typedef generator_archetype<null_archetype<> > foo;
function_requires< GeneratorConcept<foo, null_archetype<> > >();
function_requires< Generator<foo, null_archetype<> > >();
}
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
{
function_requires< GeneratorConcept< void_generator_archetype, void > >();
function_requires< Generator< void_generator_archetype, void > >();
}
#endif
{
typedef unary_function_archetype<int, int> F;
function_requires< UnaryFunctionConcept<F, int, int> >();
function_requires< UnaryFunction<F, int, int> >();
}
{
typedef binary_function_archetype<int, int, int> F;
function_requires< BinaryFunctionConcept<F, int, int, int> >();
function_requires< BinaryFunction<F, int, int, int> >();
}
{
typedef unary_predicate_archetype<int> F;
function_requires< UnaryPredicateConcept<F, int> >();
function_requires< UnaryPredicate<F, int> >();
}
{
typedef binary_predicate_archetype<int, int> F;
function_requires< BinaryPredicateConcept<F, int, int> >();
function_requires< BinaryPredicate<F, int, int> >();
}
//===========================================================================
// Iterator Concepts
{
typedef trivial_iterator_archetype<null_archetype<> > Iter;
function_requires< TrivialIteratorConcept<Iter> >();
}
{
typedef mutable_trivial_iterator_archetype<null_archetype<> > Iter;
function_requires< Mutable_TrivialIteratorConcept<Iter> >();
}
{
typedef input_iterator_archetype<null_archetype<> > Iter;
function_requires< InputIteratorConcept<Iter> >();
function_requires< InputIterator<Iter> >();
}
{
typedef output_iterator_archetype<int> Iter;
function_requires< OutputIteratorConcept<Iter, int> >();
function_requires< OutputIterator<Iter, int> >();
}
{
typedef input_output_iterator_archetype<int> Iter;
function_requires< InputIterator<Iter> >();
function_requires< OutputIterator<Iter, int> >();
}
{
typedef forward_iterator_archetype<null_archetype<> > Iter;
function_requires< ForwardIteratorConcept<Iter> >();
function_requires< ForwardIterator<Iter> >();
}
{
typedef mutable_forward_iterator_archetype<assignable_archetype<> > Iter;
function_requires< Mutable_ForwardIteratorConcept<Iter> >();
function_requires< Mutable_ForwardIterator<Iter> >();
}
{
typedef bidirectional_iterator_archetype<null_archetype<> > Iter;
function_requires< BidirectionalIteratorConcept<Iter> >();
function_requires< BidirectionalIterator<Iter> >();
}
{
typedef mutable_bidirectional_iterator_archetype<assignable_archetype<> >
Iter;
function_requires< Mutable_BidirectionalIteratorConcept<Iter> >();
function_requires< Mutable_BidirectionalIterator<Iter> >();
}
{
typedef random_access_iterator_archetype<null_archetype<> > Iter;
function_requires< RandomAccessIteratorConcept<Iter> >();
function_requires< RandomAccessIterator<Iter> >();
}
{
typedef mutable_random_access_iterator_archetype<assignable_archetype<> >
Iter;
function_requires< Mutable_RandomAccessIteratorConcept<Iter> >();
function_requires< Mutable_RandomAccessIterator<Iter> >();
}
//===========================================================================

27
test/fake_sort.hpp Normal file
View File

@ -0,0 +1,27 @@
// Copyright David Abrahams 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_LIBS_CONCEPT_CHECK_FAKE_SORT_DWA2006430_HPP
# define BOOST_LIBS_CONCEPT_CHECK_FAKE_SORT_DWA2006430_HPP
# include <iterator>
# include <boost/concept/requires.hpp>
# include <boost/concept_check.hpp>
namespace fake
{
using namespace boost;
template<typename RanIter>
BOOST_CONCEPT_REQUIRES(
((Mutable_RandomAccessIterator<RanIter>))
((LessThanComparable<typename Mutable_RandomAccessIterator<RanIter>::value_type>))
, (void))
sort(RanIter,RanIter)
{
}
}
#endif // BOOST_LIBS_CONCEPT_CHECK_FAKE_SORT_DWA2006430_HPP

View File

@ -0,0 +1,26 @@
// (C) Copyright Jeremy Siek 2000.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifdef NDEBUG
# undef NDEBUG
#endif
#include <boost/concept_check.hpp>
/*
This file verifies that function_requires() of the Boost Concept
Checking Library catches errors when it is suppose to.
*/
struct foo { };
int
main()
{
boost::function_requires< boost::EqualityComparable<foo> >();
return 0;
}

View File

@ -0,0 +1,28 @@
// (C) Copyright Jeremy Siek, David Abrahams 2000-2006.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Change Log:
// 20 Jan 2001 - Added warning suppression (David Abrahams)
#include "old_concepts.hpp"
// This file verifies that concepts written the old way still catch
// errors in class context. This is not expected to work on compilers
// without SFINAE support.
struct foo { };
class class_requires_test
{
BOOST_CLASS_REQUIRE(foo, old, EqualityComparableConcept);
};
int
main()
{
class_requires_test x;
(void)x; // suppress unused variable warning
return 0;
}

View File

@ -0,0 +1,23 @@
// (C) Copyright Jeremy Siek 2000.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifdef NDEBUG
# undef NDEBUG
#endif
#include "old_concepts.hpp"
// This file verifies that concepts written the old way still catch
// errors in function context. This is not expected to work on
// compilers without SFINAE support.
struct foo { };
int
main()
{
boost::function_requires< old::EqualityComparableConcept<foo> >();
return 0;
}

34
test/old_concept_pass.cpp Normal file
View File

@ -0,0 +1,34 @@
// (C) Copyright Jeremy Siek, David Abrahams 2000-2006.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/concept_check.hpp>
#include "old_concepts.hpp"
// This test verifies that use of the old-style concept checking
// classes still compiles (but not that it detects constraint
// violations). We check them with the old-style macros just for
// completeness, since those macros stranslate into
// BOOST_CONCEPT_ASSERTs.
struct foo { bool operator()(int) { return true; } };
struct bar { bool operator()(int, char) { return true; } };
class class_requires_test
{
BOOST_CLASS_REQUIRE(int, old, EqualityComparableConcept);
typedef int* int_ptr; typedef const int* const_int_ptr;
BOOST_CLASS_REQUIRE2(int_ptr, const_int_ptr, old, EqualOpConcept);
BOOST_CLASS_REQUIRE3(foo, bool, int, old, UnaryFunctionConcept);
BOOST_CLASS_REQUIRE4(bar, bool, int, char, old, BinaryFunctionConcept);
};
int
main()
{
class_requires_test x;
boost::ignore_unused_variable_warning(x);
return 0;
}

67
test/old_concepts.hpp Normal file
View File

@ -0,0 +1,67 @@
// Copyright Jeremy Siek, David Abrahams 2000-2006. Distributed under
// the Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_LIBS_CONCEPT_CHECK_OLD_CONCEPTS_DWA2006428_HPP
# define BOOST_LIBS_CONCEPT_CHECK_OLD_CONCEPTS_DWA2006428_HPP
#include <boost/concept_check.hpp>
namespace old
{
template <class TT>
void require_boolean_expr(const TT& t) {
bool x = t;
boost::ignore_unused_variable_warning(x);
}
template <class TT>
struct EqualityComparableConcept
{
void constraints() {
boost::require_boolean_expr(a == b);
boost::require_boolean_expr(a != b);
}
TT a, b;
};
template <class Func, class Return, class Arg>
struct UnaryFunctionConcept
{
// required in case any of our template args are const-qualified:
UnaryFunctionConcept();
void constraints() {
r = f(arg); // require operator()
}
Func f;
Arg arg;
Return r;
};
template <class Func, class Return, class First, class Second>
struct BinaryFunctionConcept
{
void constraints() {
r = f(first, second); // require operator()
}
Func f;
First first;
Second second;
Return r;
};
#define DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \
template <class First, class Second> \
struct NAME { \
void constraints() { (void)constraints_(); } \
bool constraints_() { \
return a OP b; \
} \
First a; \
Second b; \
}
DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, EqualOpConcept);
}
#endif // BOOST_LIBS_CONCEPT_CHECK_OLD_CONCEPTS_DWA2006428_HPP

View File

@ -0,0 +1,93 @@
// (C) Copyright Jeremy Siek 2000.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// This file checks to see if various standard container
// implementations live up to requirements specified in the C++
// standard. As many implementations do not live to the requirements,
// it is not uncommon for this file to fail to compile. The
// BOOST_HIDE_EXPECTED_ERRORS macro is provided here if you want to
// see as much of this file compile as possible.
//
#include <boost/concept_check.hpp>
#include <iterator>
#include <set>
#include <map>
#include <vector>
#include <list>
#include <deque>
#if 0
#include <slist>
#endif
// Define this macro if you want to hide the expected error, that is,
// error in the various C++ standard library implementations.
//
//#define BOOST_HIDE_EXPECTED_ERRORS
int
main()
{
using namespace boost;
#if defined(_ITERATOR_) && defined(BOOST_HIDE_EXPECTED_ERRORS)
// VC++ STL implementation is not standard conformant and
// fails to pass these concept checks
#else
typedef std::vector<int> Vector;
typedef std::deque<int> Deque;
typedef std::list<int> List;
// VC++ missing pointer and const_pointer typedefs
function_requires< Mutable_RandomAccessContainer<Vector> >();
function_requires< BackInsertionSequence<Vector> >();
#if !(defined(__GNUC__) && defined(BOOST_HIDE_EXPECTED_ERRORS))
#if !((defined(__sgi) || (defined(__DECCXX) && defined(_RWSTD_VER) && _RWSTD_VER <= 0x0203)) \
&& defined(BOOST_HIDE_EXPECTED_ERRORS))
// old deque iterator missing n + iter operation
function_requires< Mutable_RandomAccessContainer<Deque> >();
#endif
// warnings about signed and unsigned in old deque version
function_requires< FrontInsertionSequence<Deque> >();
function_requires< BackInsertionSequence<Deque> >();
#endif
// VC++ missing pointer and const_pointer typedefs
function_requires< Mutable_ReversibleContainer<List> >();
function_requires< FrontInsertionSequence<List> >();
function_requires< BackInsertionSequence<List> >();
#if 0
typedef BOOST_STD_EXTENSION_NAMESPACE::slist<int> SList;
function_requires< FrontInsertionSequence<SList> >();
#endif
typedef std::set<int> Set;
typedef std::multiset<int> MultiSet;
typedef std::map<int,int> Map;
typedef std::multimap<int,int> MultiMap;
function_requires< SortedAssociativeContainer<Set> >();
function_requires< SimpleAssociativeContainer<Set> >();
function_requires< UniqueAssociativeContainer<Set> >();
function_requires< SortedAssociativeContainer<MultiSet> >();
function_requires< SimpleAssociativeContainer<MultiSet> >();
function_requires< MultipleAssociativeContainer<MultiSet> >();
function_requires< SortedAssociativeContainer<Map> >();
function_requires< UniqueAssociativeContainer<Map> >();
function_requires< PairAssociativeContainer<Map> >();
function_requires< SortedAssociativeContainer<MultiMap> >();
function_requires< MultipleAssociativeContainer<MultiMap> >();
function_requires< PairAssociativeContainer<MultiMap> >();
#endif
return 0;
}

View File

@ -1,13 +1,13 @@
// (C) Copyright Jeremy Siek 2000-2002. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
// (C) Copyright Jeremy Siek 2000-2002.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/concept_check.hpp>
#include <boost/concept_archetype.hpp>
#include <algorithm>
#include <numeric>
#include <boost/config.hpp>
#include <boost/concept_check.hpp>
#include <boost/concept_archetype.hpp>
/*
@ -25,6 +25,21 @@
*/
/**
* Input iterator - explanation from Peter Dimov:
*
* Requirements say that *it is convertible to the value_type, and it is, in
* our case. The problem however is that op== is a template and the first
* argument fails deduction. std::find is specified in terms of the exact
* expression `*it == value`, so if it doesn't compile (and it doesn't),
* `find(it, it, value)` won't compile either.
*
* To address this, the no_proxy variant of the input iterator is used
* instead.
*/
#define BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE input_iterator_archetype_no_proxy
boost::detail::dummy_constructor dummy_cons;
// This is a special concept needed for std::swap_ranges.
@ -63,6 +78,17 @@ namespace accum
}
}
// for std::shuffle
namespace shuffle
{
struct URBG {
typedef unsigned int result_type;
result_type BOOST_CONSTEXPR static min() { return 0; }
result_type BOOST_CONSTEXPR static max() { return 1; }
result_type operator()() { return 1; }
};
}
// for std::inner_product
namespace inner_prod
{
@ -93,22 +119,19 @@ namespace boost { // so Koenig lookup will find
// for std::partial_sum and adj_diff
namespace part_sum
{
typedef boost::null_archetype<> Tout;
typedef boost::sgi_assignable_archetype<
boost::convertible_to_archetype<Tout> > Ret;
class Tin {
class T {
public:
Tin(const Ret&) { }
Tin(boost::detail::dummy_constructor x) { }
operator const Tout&() const { return boost::static_object<Tout>::get(); }
typedef boost::sgi_assignable_archetype<> Ret;
T(const Ret&) { }
T(boost::detail::dummy_constructor x) { }
private:
Tin() { }
T() { }
};
Ret operator+(const Tin&, const Tin&) {
return Ret(dummy_cons);
T::Ret operator+(const T&, const T&) {
return T::Ret(dummy_cons);
}
Ret operator-(const Tin&, const Tin&) {
return Ret(dummy_cons);
T::Ret operator-(const T&, const T&) {
return T::Ret(dummy_cons);
}
}
@ -130,6 +153,7 @@ namespace power_stuff {
struct tag1 { };
struct tag2 { };
int
main()
{
@ -138,22 +162,22 @@ main()
//===========================================================================
// Non-mutating Algorithms
{
input_iterator_archetype<
convertible_to_archetype< null_archetype<> > > in;
input_iterator_archetype< null_archetype<> > in;
unary_function_archetype< null_archetype<> , null_archetype<> >
f(dummy_cons);
std::for_each(in, in, f);
}
// gcc bug
{
typedef equality_comparable2_first_archetype<> Left;
input_iterator_archetype< Left > in;
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE< Left > in;
equality_comparable2_second_archetype<> value(dummy_cons);
in = std::find(in, in, value);
}
{
input_iterator_archetype<
convertible_to_archetype< null_archetype<> > > in;
unary_predicate_archetype< null_archetype<> > pred(dummy_cons);
typedef null_archetype<> T;
input_iterator_archetype<T> in;
unary_predicate_archetype<T> pred(dummy_cons);
in = std::find_if(in, in, pred);
}
{
@ -167,61 +191,62 @@ main()
pred(dummy_cons);
fo = std::adjacent_find(fo, fo, pred);
}
// gcc bug
{
typedef equal_op_first_archetype<> Left;
input_iterator_archetype<Left> in;
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Left> in;
typedef equal_op_second_archetype<> Right;
forward_iterator_archetype<Right> fo;
in = std::find_first_of(in, in, fo, fo);
}
{
typedef equal_op_first_archetype<> Left;
typedef input_iterator_archetype<Left> InIter;
typedef BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Left> InIter;
InIter in;
function_requires< InputIteratorConcept<InIter> >();
function_requires< InputIterator<InIter> >();
equal_op_second_archetype<> value(dummy_cons);
std::iterator_traits<InIter>::difference_type
n = std::count(in, in, value);
ignore_unused_variable_warning(n);
}
{
typedef input_iterator_archetype<
convertible_to_archetype<null_archetype<> > > InIter;
typedef input_iterator_archetype< null_archetype<> > InIter;
InIter in;
unary_predicate_archetype<null_archetype<> > pred(dummy_cons);
std::iterator_traits<InIter>::difference_type
n = std::count_if(in, in, pred);
ignore_unused_variable_warning(n);
}
// gcc bug
{
typedef equal_op_first_archetype<> Left;
typedef input_iterator_archetype<Left> InIter1;
typedef BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Left> InIter1;
InIter1 in1;
typedef equal_op_second_archetype<> Right;
typedef input_iterator_archetype<Right> InIter2;
typedef BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Right> InIter2;
InIter2 in2;
std::pair<InIter1, InIter2> p = std::mismatch(in1, in1, in2);
ignore_unused_variable_warning(p);
}
{
typedef input_iterator_archetype<
convertible_to_archetype<null_archetype<> > > InIter;
typedef input_iterator_archetype<null_archetype<> > InIter;
InIter in1, in2;
binary_predicate_archetype<null_archetype<> , null_archetype<> >
pred(dummy_cons);
std::pair<InIter, InIter> p = std::mismatch(in1, in1, in2, pred);
ignore_unused_variable_warning(p);
}
// gcc bug
{
typedef equality_comparable2_first_archetype<> Left;
input_iterator_archetype<Left> in1;
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Left> in1;
typedef equality_comparable2_second_archetype<> Right;
input_iterator_archetype<Right> in2;
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Right> in2;
bool b = std::equal(in1, in1, in2);
ignore_unused_variable_warning(b);
}
{
input_iterator_archetype< convertible_to_archetype<null_archetype<> > >
input_iterator_archetype< null_archetype<> >
in1, in2;
binary_predicate_archetype<null_archetype<> , null_archetype<> >
pred(dummy_cons);
@ -286,10 +311,9 @@ main()
// Mutating Algorithms
{
typedef null_archetype<> OutT;
typedef convertible_to_archetype<OutT> InT;
input_iterator_archetype<InT> in;
output_iterator_archetype<OutT> out(dummy_cons);
typedef null_archetype<> T;
input_iterator_archetype<T> in;
output_iterator_archetype<T> out(dummy_cons);
out = std::copy(in, in, out);
}
{
@ -308,16 +332,19 @@ main()
mutable_forward_iterator_archetype<T> a, b;
std::iter_swap(a, b);
}
#if 0
{
// fails on gcc 7.3 and clang 6.0
typedef mutually_convertible_archetype<int> Tin;
typedef mutually_convertible_archetype<char> Tout;
mutable_forward_iterator_archetype<Tin> fi1;
mutable_forward_iterator_archetype<Tout> fi2;
fi2 = std::swap_ranges(fi1, fi1, fi2);
}
#endif
{
typedef convertible_to_archetype<null_archetype<> > Tin;
typedef null_archetype<> Tout;
typedef null_archetype<int> Tin;
typedef null_archetype<char> Tout;
input_iterator_archetype<Tin> in;
output_iterator_archetype<Tout> out(dummy_cons);
unary_function_archetype<null_archetype<> ,
@ -325,13 +352,13 @@ main()
out = std::transform(in, in, out, op);
}
{
typedef convertible_to_archetype<null_archetype<int> > Tin1;
typedef convertible_to_archetype<null_archetype<char> > Tin2;
typedef null_archetype<> Tout;
typedef null_archetype<int> Tin1;
typedef null_archetype<char> Tin2;
typedef null_archetype<double> Tout;
input_iterator_archetype<Tin1> in1;
input_iterator_archetype<Tin2> in2;
output_iterator_archetype<Tout> out(dummy_cons);
binary_function_archetype<null_archetype<int>, null_archetype<char>,
binary_function_archetype<Tin1, Tin2,
convertible_to_archetype<Tout> > op(dummy_cons);
out = std::transform(in1, in1, in2, out, op);
}
@ -352,45 +379,29 @@ main()
convertible_to_archetype<FT> value(dummy_cons);
std::replace_if(fi, fi, pred, value);
}
#if (!defined(BOOST_MSVC) || BOOST_WORKAROUND(BOOST_MSVC, > 1900)) && !defined(BOOST_EMBTC)
// fails on MSVC 2015 and earlier
{
#if 0
// Issue, the use of ?: inside replace_copy() complicates things
typedef equal_op_first_archetype<> Tin;
typedef null_archetype<> Tout;
typedef equal_op_second_archetype< convertible_to_archetype<Tout> > T;
input_iterator_archetype<Tin> in;
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Tin> in;
output_iterator_archetype<Tout> out(dummy_cons);
T value(dummy_cons);
out = std::replace_copy(in, in, out, value, value);
#else
typedef null_archetype<> Tout;
typedef equal_op_second_archetype< convertible_to_archetype<Tout> > T;
// Adding convertible to T for Tin solves the problem, so would
// making T convertible to Tin. Not sure what the right way to
// express the requirement would be. Also, perhaps the
// implementation's use of ?: is invalid.
typedef equal_op_first_archetype< convertible_to_archetype<T> > Tin;
input_iterator_archetype<Tin> in;
output_iterator_archetype<Tout> out(dummy_cons);
T value(dummy_cons);
out = std::replace_copy(in, in, out, value, value);
#endif
}
{
// The issue of ?: also affects this function
typedef null_archetype<int> PredArg;
typedef null_archetype<char> Tout;
typedef convertible_to_archetype<Tout,
convertible_to_archetype<PredArg> > T;
typedef convertible_to_archetype<PredArg,
convertible_to_archetype<Tout,
convertible_to_archetype<T> > > Tin;
input_iterator_archetype<Tin> in;
typedef null_archetype<> Tout;
typedef assignable_archetype< convertible_to_archetype<Tout> > Tin;
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Tin> in;
output_iterator_archetype<Tout> out(dummy_cons);
unary_predicate_archetype<PredArg> pred(dummy_cons);
T value(dummy_cons);
unary_predicate_archetype<Tin> pred(dummy_cons);
Tin value(dummy_cons);
out = std::replace_copy_if(in, in, out, pred, value);
}
#endif
{
typedef assignable_archetype<> FT;
mutable_forward_iterator_archetype<FT> fi;
@ -398,6 +409,8 @@ main()
T value(dummy_cons);
std::fill(fi, fi, value);
}
#if !defined(BOOST_MSVC) || BOOST_WORKAROUND(BOOST_MSVC, >= 1700)
// fails on MSVC 2010
{
typedef null_archetype<> Tout;
typedef convertible_to_archetype<Tout> T;
@ -406,6 +419,7 @@ main()
int n = 1;
out = std::fill_n(out, n, value);
}
#endif
{
typedef assignable_archetype<> FT;
typedef convertible_to_archetype<FT> Ret;
@ -435,24 +449,22 @@ main()
unary_predicate_archetype<PredArg> pred(dummy_cons);
fi = std::remove_if(fi, fi, pred);
}
// gcc bug
{
typedef null_archetype<> Tout;
typedef equality_comparable2_first_archetype<
convertible_to_archetype<Tout> > Tin;
typedef equality_comparable2_second_archetype<> T;
input_iterator_archetype<Tin> in;
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Tin> in;
output_iterator_archetype<Tout> out(dummy_cons);
T value(dummy_cons);
out = std::remove_copy(in, in, out, value);
}
{
typedef null_archetype<int> Tout;
typedef null_archetype<char> PredArg;
typedef convertible_to_archetype<PredArg,
convertible_to_archetype<Tout> > Tin;
input_iterator_archetype<Tin> in;
output_iterator_archetype<Tout> out(dummy_cons);
unary_predicate_archetype<PredArg> pred(dummy_cons);
typedef null_archetype<> T;
input_iterator_archetype<T> in;
output_iterator_archetype<T> out(dummy_cons);
unary_predicate_archetype<T> pred(dummy_cons);
out = std::remove_copy_if(in, in, out, pred);
}
{
@ -470,23 +482,18 @@ main()
binary_predicate_archetype<Arg1, Arg2> pred(dummy_cons);
fi = std::unique(fi, fi, pred);
}
// gcc bug
{
typedef equality_comparable_archetype< sgi_assignable_archetype<> > T;
input_iterator_archetype<T> in;
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<T> in;
output_iterator_archetype<T> out(dummy_cons);
out = std::unique_copy(in, in, out);
}
{
typedef null_archetype<int> Arg1;
typedef null_archetype<char> Arg2;
typedef null_archetype<short> Tout;
typedef sgi_assignable_archetype<
convertible_to_archetype<Tout,
convertible_to_archetype<Arg1,
convertible_to_archetype<Arg2> > > > Tin;
input_iterator_archetype<Tin> in;
output_iterator_archetype<Tout> out(dummy_cons);
binary_predicate_archetype<Arg1, Arg2> pred(dummy_cons);
typedef sgi_assignable_archetype<> T;
input_iterator_archetype<T> in;
output_iterator_archetype<T> out(dummy_cons);
binary_predicate_archetype<T, T> pred(dummy_cons);
out = std::unique_copy(in, in, out, pred);
}
{
@ -514,6 +521,7 @@ main()
output_iterator_archetype<Tout> out(dummy_cons);
out = std::rotate_copy(fi, fi, fi, out);
}
#ifndef BOOST_NO_CXX98_RANDOM_SHUFFLE
{
typedef sgi_assignable_archetype<> T;
mutable_random_access_iterator_archetype<T> ri;
@ -525,6 +533,14 @@ main()
unary_function_archetype<std::ptrdiff_t, std::ptrdiff_t> ran(dummy_cons);
std::random_shuffle(ri, ri, ran);
}
#else
{
typedef sgi_assignable_archetype<> T;
mutable_random_access_iterator_archetype<T> ri;
shuffle::URBG urbg;
std::shuffle(ri, ri, urbg);
}
#endif
{
typedef null_archetype<> PredArg;
typedef sgi_assignable_archetype<convertible_to_archetype<PredArg> > FT;
@ -532,14 +548,17 @@ main()
unary_predicate_archetype<PredArg> pred(dummy_cons);
bi = std::partition(bi, bi, pred);
}
#if !defined(BOOST_MSVC) && !defined(BOOST_EMBTC) && !defined(_MSC_VER)
{
// fails on MSVC and clang-win; stl headers come from Visual Studio and
// they attempt to reverse the iterator
typedef null_archetype<> PredArg;
typedef sgi_assignable_archetype<convertible_to_archetype<PredArg> > FT;
mutable_forward_iterator_archetype<FT> fi;
unary_predicate_archetype<PredArg> pred(dummy_cons);
fi = std::stable_partition(fi, fi, pred);
}
#endif
//===========================================================================
// Sorting Algorithms
{
@ -585,22 +604,21 @@ main()
binary_predicate_archetype<Arg, Arg> comp(dummy_cons);
std::partial_sort(ri, ri, ri, comp);
}
// gcc bug
{
// This could be formulated so that the two iterators are not
// required to have the same value type, but it is messy.
typedef sgi_assignable_archetype<
less_than_comparable_archetype<> > T;
input_iterator_archetype<T> in;
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<T> in;
mutable_random_access_iterator_archetype<T> ri_out;
ri_out = std::partial_sort_copy(in, in , ri_out, ri_out);
}
{
typedef null_archetype<> Arg;
typedef sgi_assignable_archetype<
convertible_to_archetype<Arg> > T;
typedef sgi_assignable_archetype<> T;
input_iterator_archetype<T> in;
mutable_random_access_iterator_archetype<T> ri_out;
binary_predicate_archetype<Arg, Arg> comp(dummy_cons);
binary_predicate_archetype<T, T> comp(dummy_cons);
ri_out = std::partial_sort_copy(in, in , ri_out, ri_out, comp);
}
{
@ -619,14 +637,14 @@ main()
std::nth_element(ri, ri, ri, comp);
}
{
#if defined(__GNUC__)
typedef less_than_op_first_archetype<> FT;
typedef less_than_op_second_archetype<> T;
#elif defined(__KCC)
#if defined(__KCC)
// The KAI version of this uses a one-argument less-than function
// object.
typedef less_than_comparable_archetype<> T;
typedef convertible_to_archetype<T> FT;
#else
typedef less_than_op_first_archetype<> FT;
typedef less_than_op_second_archetype<> T;
#endif
forward_iterator_archetype<FT> fi;
T value(dummy_cons);
@ -643,13 +661,13 @@ main()
fi = std::lower_bound(fi, fi, value, comp);
}
{
#if defined(__GNUC__)
#if defined(__KCC)
typedef less_than_comparable_archetype<> T;
typedef convertible_to_archetype<T> FT;
#else
// Note, order of T,FT is flipped from lower_bound
typedef less_than_op_second_archetype<> FT;
typedef less_than_op_first_archetype<> T;
#elif defined(__KCC)
typedef less_than_comparable_archetype<> T;
typedef convertible_to_archetype<T> FT;
#endif
forward_iterator_archetype<FT> fi;
T value(dummy_cons);
@ -666,15 +684,17 @@ main()
binary_predicate_archetype<Arg1, Arg2> comp(dummy_cons);
fi = std::upper_bound(fi, fi, value, comp);
}
#if !defined(BOOST_MSVC) || BOOST_WORKAROUND(BOOST_MSVC, >= 1900)
// Fails on MSVC 2013 and earlier
{
#if defined(__GNUC__)
#if defined(__KCC)
typedef less_than_comparable_archetype<> T;
typedef convertible_to_archetype<T> FT;
#else
typedef less_than_op_first_archetype<
less_than_op_second_archetype< null_archetype<>, optag2>, optag1> FT;
typedef less_than_op_second_archetype<
less_than_op_first_archetype< null_archetype<>, optag2>, optag1> T;
#elif defined(__KCC)
typedef less_than_comparable_archetype<> T;
typedef convertible_to_archetype<T> FT;
#endif
typedef forward_iterator_archetype<FT> FIter;
FIter fi;
@ -682,6 +702,7 @@ main()
std::pair<FIter,FIter> p = std::equal_range(fi, fi, value);
ignore_unused_variable_warning(p);
}
#endif
{
typedef null_archetype<int> Arg1;
typedef null_archetype<char> Arg2;
@ -697,14 +718,14 @@ main()
ignore_unused_variable_warning(p);
}
{
#if defined(__GNUC__)
#if defined(__KCC)
typedef less_than_op_first_archetype< less_than_comparable_archetype<> > T;
typedef less_than_op_second_archetype< convertible_to_archetype<T> > FT;
#else
typedef less_than_op_first_archetype<
less_than_op_second_archetype<null_archetype<>, optag2>, optag1> FT;
typedef less_than_op_second_archetype<
less_than_op_first_archetype<null_archetype<>, optag2>, optag1> T;
#elif defined(__KCC)
typedef less_than_op_first_archetype< less_than_comparable_archetype<> > T;
typedef less_than_op_second_archetype< convertible_to_archetype<T> > FT;
#endif
forward_iterator_archetype<FT> fi;
T value(dummy_cons);
@ -714,12 +735,10 @@ main()
{
typedef null_archetype<int> Arg1;
typedef null_archetype<char> Arg2;
#if defined(__GNUC__) || defined(__KCC)
typedef convertible_to_archetype<Arg1,
convertible_to_archetype<Arg2> > FT;
typedef convertible_to_archetype<Arg2,
convertible_to_archetype<Arg1> > T;
#endif
typedef forward_iterator_archetype<FT> FIter;
FIter fi;
T value(dummy_cons);
@ -729,16 +748,15 @@ main()
}
{
typedef null_archetype<> Tout;
#if defined(__GNUC__) || defined(__KCC)
typedef less_than_op_first_archetype<
less_than_op_second_archetype<
convertible_to_archetype<Tout>, optag2>, optag1 > Tin1;
typedef less_than_op_second_archetype<
less_than_op_first_archetype<
convertible_to_archetype<Tout>, optag2> ,optag1> Tin2;
#endif
input_iterator_archetype<Tin1> in1;
input_iterator_archetype<Tin2> in2;
// gcc bug
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Tin1> in1;
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Tin2> in2;
output_iterator_archetype<Tout> out(dummy_cons);
out = std::merge(in1, in1, in2, in2, out);
out = std::set_union(in1, in1, in2, in2, out);
@ -747,21 +765,11 @@ main()
out = std::set_symmetric_difference(in1, in1, in2, in2, out);
}
{
typedef null_archetype<int> Arg1;
typedef null_archetype<char> Arg2;
typedef null_archetype<short> Tout;
#if defined(__GNUC__) || defined(__KCC)
typedef convertible_to_archetype<Tout,
convertible_to_archetype<Arg1,
convertible_to_archetype<Arg2> > > Tin1;
typedef convertible_to_archetype<Tout,
convertible_to_archetype<Arg2,
convertible_to_archetype<Arg1> > > Tin2;
#endif
input_iterator_archetype<Tin1> in1;
input_iterator_archetype<Tin2> in2;
output_iterator_archetype<Tout> out(dummy_cons);
binary_predicate_archetype<Arg1, Arg2> comp(dummy_cons);
typedef null_archetype<> T;
input_iterator_archetype<T> in1;
input_iterator_archetype<T,2> in2;
output_iterator_archetype<T> out(dummy_cons);
binary_predicate_archetype<T, T> comp(dummy_cons);
out = std::merge(in1, in1, in2, in2, out, comp);
out = std::set_union(in1, in1, in2, in2, out, comp);
out = std::set_intersection(in1, in1, in2, in2, out, comp);
@ -782,31 +790,23 @@ main()
binary_predicate_archetype<Arg, Arg> comp(dummy_cons);
std::inplace_merge(bi, bi, bi, comp);
}
// gcc bug
{
#if defined(__GNUC__) || defined(__KCC)
typedef less_than_op_first_archetype<
less_than_op_second_archetype<null_archetype<>, optag1>, optag2> Tin1;
typedef less_than_op_second_archetype<
less_than_op_first_archetype<null_archetype<>, optag1>, optag2> Tin2;
#endif
input_iterator_archetype<Tin1> in1;
input_iterator_archetype<Tin2> in2;
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Tin1> in1;
BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Tin2> in2;
bool b = std::includes(in1, in1, in2, in2);
b = std::lexicographical_compare(in1, in1, in2, in2);
ignore_unused_variable_warning(b);
}
{
typedef null_archetype<int> Arg1;
typedef null_archetype<char> Arg2;
#if defined(__GNUC__) || defined(__KCC)
typedef convertible_to_archetype<Arg1,
convertible_to_archetype<Arg2> > Tin1;
typedef convertible_to_archetype<Arg2,
convertible_to_archetype<Arg1> > Tin2;
#endif
input_iterator_archetype<Tin1> in1;
input_iterator_archetype<Tin2> in2;
binary_predicate_archetype<Arg1, Arg2> comp(dummy_cons);
typedef null_archetype<int> Tin;
input_iterator_archetype<Tin> in1;
input_iterator_archetype<Tin,1> in2;
binary_predicate_archetype<Tin, Tin> comp(dummy_cons);
bool b = std::includes(in1, in1, in2, in2, comp);
b = std::lexicographical_compare(in1, in1, in2, in2, comp);
ignore_unused_variable_warning(b);
@ -834,8 +834,10 @@ main()
{
typedef less_than_comparable_archetype<> T;
T a(dummy_cons), b(dummy_cons);
const T& c = std::min(a, b);
const T& d = std::max(a, b);
BOOST_USING_STD_MIN();
BOOST_USING_STD_MAX();
const T& c = min BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
const T& d = max BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
ignore_unused_variable_warning(c);
ignore_unused_variable_warning(d);
}
@ -844,8 +846,10 @@ main()
binary_predicate_archetype<Arg, Arg> comp(dummy_cons);
typedef convertible_to_archetype<Arg> T;
T a(dummy_cons), b(dummy_cons);
const T& c = std::min(a, b, comp);
const T& d = std::max(a, b, comp);
BOOST_USING_STD_MIN();
BOOST_USING_STD_MAX();
const T& c = min BOOST_PREVENT_MACRO_SUBSTITUTION(a, b, comp);
const T& d = max BOOST_PREVENT_MACRO_SUBSTITUTION(a, b, comp);
ignore_unused_variable_warning(c);
ignore_unused_variable_warning(d);
}
@ -897,8 +901,7 @@ main()
typedef sgi_assignable_archetype<
convertible_to_archetype<Arg1> > T;
typedef convertible_to_archetype<T> Ret;
typedef convertible_to_archetype<Arg2> Tin;
input_iterator_archetype<Tin> in;
input_iterator_archetype<Arg2> in;
T init(dummy_cons);
binary_function_archetype<Arg1, Arg2, Ret> op(dummy_cons);
init = std::accumulate(in, in, init, op);
@ -918,38 +921,30 @@ main()
convertible_to_archetype<AddArg1> > T;
typedef convertible_to_archetype<AddArg2> RetMult;
typedef convertible_to_archetype<T> RetAdd;
typedef convertible_to_archetype<MultArg1> Tin1;
typedef convertible_to_archetype<MultArg2> Tin2;
input_iterator_archetype<Tin1> in1;
input_iterator_archetype<Tin2> in2;
input_iterator_archetype<MultArg1> in1;
input_iterator_archetype<MultArg2> in2;
T init(dummy_cons);
binary_function_archetype<MultArg1, MultArg2, RetMult> mult_op(dummy_cons);
binary_function_archetype<AddArg1, AddArg2, RetAdd> add_op(dummy_cons);
init = std::inner_product(in1, in1, in2, init, add_op, mult_op);
}
{
input_iterator_archetype<part_sum::Tin> in;
output_iterator_archetype<part_sum::Tout> out(dummy_cons);
input_iterator_archetype<part_sum::T> in;
output_iterator_archetype<part_sum::T> out(dummy_cons);
out = std::partial_sum(in, in, out);
}
{
typedef null_archetype<int> Arg;
typedef null_archetype<char> Tout;
typedef sgi_assignable_archetype<
convertible_to_archetype<Arg,
convertible_to_archetype<Tout> > > Tin;
typedef convertible_to_archetype<Tout,
convertible_to_archetype<Tin> > Ret;
input_iterator_archetype<Tin> in;
output_iterator_archetype<Tout> out(dummy_cons);
binary_function_archetype<Arg, Arg, Ret> add_op(dummy_cons);
typedef sgi_assignable_archetype<> T;
input_iterator_archetype<T> in;
output_iterator_archetype<T> out(dummy_cons);
binary_function_archetype<T, T, T> add_op(dummy_cons);
out = std::partial_sum(in, in, out, add_op);
binary_function_archetype<Arg, Arg, Ret> subtract_op(dummy_cons);
binary_function_archetype<T, T, T> subtract_op(dummy_cons);
out = std::adjacent_difference(in, in, out, subtract_op);
}
{
input_iterator_archetype<part_sum::Tin> in;
output_iterator_archetype<part_sum::Tout> out(dummy_cons);
input_iterator_archetype<part_sum::T> in;
output_iterator_archetype<part_sum::T> out(dummy_cons);
out = std::adjacent_difference(in, in, out);
}
return 0;

24
test/usage_fail.cpp Normal file
View File

@ -0,0 +1,24 @@
// Copyright David Abrahams 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/concept/usage.hpp>
#include <boost/core/ignore_unused.hpp>
template <class T>
struct StringInitializable
{
typedef int associated;
BOOST_CONCEPT_USAGE(StringInitializable)
{
T x = "foo";
boost::ignore_unused(x);
}
};
// Test that accessing an associated type will actually exercise usage
// requirements
typedef StringInitializable<int>::associated tee;

13
test/where.cpp Normal file
View File

@ -0,0 +1,13 @@
// Copyright David Abrahams 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <vector>
#undef NDEBUG
#include "fake_sort.hpp"
int main()
{
std::vector<int> v;
fake::sort(v.begin(), v.end());
return 0;
}

13
test/where_fail.cpp Normal file
View File

@ -0,0 +1,13 @@
// Copyright David Abrahams 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <list>
#undef NDEBUG
#include "fake_sort.hpp"
int main()
{
std::list<int> v;
fake::sort(v.begin(), v.end());
return 0;
}

View File

@ -1,225 +1,186 @@
<HTML>
<!--
-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. We make no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
-->
<Head>
<Title>Using Concept Checks</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<BR Clear>
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000 -->
<!-- Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<head>
<meta name="generator" content=
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" />
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
<h2><a name="using-concept-checks">Using Concept Checks</a></h2>
<title>Using Concept Checks</title>
<link rel="stylesheet" href="../../rst.css" type="text/css" />
</head>
For each concept there is a concept checking class which can be used
to make sure that a given type (or set of types) models the concept.
The Boost Concept Checking Library (BCCL) includes concept checking classes
for all of the concepts used in the C++ standard library and a few
more. The <a href="./reference.htm">Reference</a> section lists these
concept checking classes. In addition, other boost libraries come with
concept checking classes for the concepts that are particular to those
libraries. For example, there are <a
href="../graph/doc/graph_concepts.html">graph concepts</a> and <a
href="../property_map/property_map.html">property map concepts</a>.
Also, whenever <b>anyone</b> writing a class of function template
needs to express requirements that are not yet stated by an existing
concept, a new concept checking class should be created. How
to do this is explained in <a href="./creating_concepts.htm">Creating
Concept Checking Classes</a>.
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
"#FF0000">
<img src="../../boost.png" alt="C++ Boost" width="277" height=
"86" /><br clear="none" />
<p>
An example of a concept checking class from the BCCL is the
<tt>EqualityComparableConcept</tt> class. The class corresponds to the
EqualityComparable requirements described in 20.1.1 of the C++
Standard, and to the <a
href="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a>
concept documented in the SGI STL.
<h2><a name="using-concept-checks" id="using-concept-checks">Using Concept
Checks</a></h2>
<pre>
template &lt;class T&gt;
struct EqualityComparableConcept;
<p>For each concept there is a concept checking class template that can be
used to make sure that a given type (or set of types) models the concept.
The Boost Concept Checking Library (BCCL) includes concept checking class
templates for all of the concepts used in the C++ standard library and a
few more. See the <a href="./reference.htm">Reference</a> section for a
complete list. In addition, other boost libraries come with concept
checking classes for the concepts that are particular to those libraries.
For example, there are <a href="../graph/doc/graph_concepts.html">graph
concepts</a> and <a href="../property_map/doc/property_map.html">property map
concepts</a>. Also, whenever <b>anyone</b> writing function templates needs
to express requirements that are not yet stated by an existing concept, a
new concept checking class should be created. How to do this is explained
in <a href="./creating_concepts.htm">Creating Concept Checking
Classes</a>.</p>
<p>An example of a concept checking class from the BCCL is the
<tt>EqualityComparableConcept</tt> class. The class corresponds to the
EqualityComparable requirements described in 20.1.1 of the C++ Standard,
and to the <a href=
"http://www.boost.org/sgi/stl/EqualityComparable.html">EqualityComparable</a>
concept documented in the SGI STL.</p>
<pre>
template &lt;class T&gt;
struct EqualityComparable;
</pre>
The template argument <tt>T</tt> will the type to be checked. That is,
the purpose of <tt>EqualityComparableConcept</tt> is to make sure that
the template argument given for <tt>T</tt> models the
EqualityComparable concept.
<p>The template argument is the type to be checked. That is, the purpose of
<tt>EqualityComparable&lt;<em>T</em>&gt;</tt> is to make sure that
<tt><em>T</em></tt> models the EqualityComparable concept.</p>
<p>
Each concept checking class has a member function named
<tt>constraints()</tt> which contains the valid expressions for the
concept. To check whether some type is EqualityComparable we need to
instantiate the concept checking class with the type and then find a
way to get the compiler to compile the <tt>constraints()</tt> function
without actually executing the function. The Boost Concept Checking
Library defines two utilities that make this easy:
<tt>function_requires()</tt> and <tt>BOOST_CLASS_REQUIRE</tt>.
<h4><tt>BOOST_CONCEPT_ASSERT()</tt></h4>
<h4><tt>function_requires()</tt></h4>
<p>The most versatile way of checking concept requirements is to use the
<code>BOOST_CONCEPT_ASSERT()</code> macro. You can use this macro at any
scope, by passing a concept checking template specialization enclosed in
parentheses. <strong>Note:</strong> that means invocations of
<code>BOOST_CONCEPT_ASSERT</code> will appear to use <strong>double
parentheses</strong>.</p>
<pre>
<font color="green">// In my library:</font>
template &lt;class T&gt;
void generic_library_function(T x)
{
BOOST_CONCEPT_ASSERT<strong>((</strong>EqualityComparable&lt;T&gt;<strong>))</strong>;
<font color="green">// ...</font>
};
The <tt>function_requires()</tt> function can be used in function bodies
and the <tt>BOOST_CLASS_REQUIRE</tt> macro can be used inside class
bodies. The <tt>function_requires()</tt> function takes no arguments,
but has a template parameter for the concept checking class. This
means that the instantiated concept checking class must be given as an
explicit template argument, as shown below.
template &lt;class It&gt;
class generic_library_class
{
BOOST_CONCEPT_ASSERT<strong>((</strong>RandomAccessIterator&lt;It&gt;<strong>))</strong>;
<font color="green">// ...</font>
};
<pre>
// In my library:
template &lt;class T&gt;
void generic_library_function(T x)
{
function_requires&lt; EqualityComparableConcept&lt;T&gt; &gt;();
// ...
};
<font color="green">// In the user's code:</font>
class foo {
<font color="green">//... </font>
};
// In the user's code:
class foo {
//...
};
int main() {
foo f;
generic_library_function(f);
return 0;
}
int main() {
foo x;
generic_library_function(x);
generic_library_class&lt;std::vector&lt;char&gt;::iterator&gt; y;
<font color="green">//...</font>
}
</pre>
<h4><tt>BOOST_CONCEPT_REQUIRES</tt></h4>
<h4><tt>BOOST_CLASS_REQUIRE</tt></h4>
<p>One of the nice things about the proposed C++0x <a href=
"http://www.generic-programming.org/languages/conceptcpp/tutorial">syntax
for declaring concept constrained function templates</a> is the way that
constraints are part of the function <em>declaration</em>, so clients will
see them. <code>BOOST_CONCEPT_ASSERT</code> can only express constraints
within the function template definition, which hides the constraint in the
function body. Aside from the loss of a self-documenting interface,
asserting conformance only in the function body can undesirably delay
checking if the function is explicitly instantiated in a different
translation unit from the one in which it is called, or if the compiler
does link-time instantiation.</p>
The <tt>BOOST_CLASS_REQUIRE</tt> macro can be used inside a class
definition to check whether some type models a concept.
<pre>
// In my library:
template &lt;class T&gt;
struct generic_library_class
{
BOOST_CLASS_REQUIRE(T, boost, EqualityComparableConcept);
// ...
};
// In the user's code:
class foo {
//...
};
int main() {
generic_library_class&lt;foo&gt; glc;
// ...
return 0;
}
<p>The <tt>BOOST_CONCEPT_REQUIRES</tt> macro can be used in a function
template declaration to check whether some type models a concept. It
accepts two arguments, a <strong>list of constraints</strong>, and the
function template's return type. The list of constraints takes the form of
a sequence of adjacent concept checking template specializations,
<strong>in double parentheses</strong>, and the function's return type must
also be parenthesized. For example, the standard <code>stable_sort</code>
algorithm might be declared as follows: </p>
<pre>
template &lt;class RanIter&gt;
BOOST_CONCEPT_REQUIRES(
((Mutable_RandomAccessIterator&lt;RanIter&gt;))
((LessThanComparable&lt;typename Mutable_RandomAccessIterator&lt;RanIter&gt;::value_type&gt;)),
(void)) <font color="green">// return type</font>
stable_sort(RanIter,RanIter);
</pre>
<p>Note that the algorithm requires that the value type of the iterator be
LessThanComparable, and it accesses that value type through the
<code>Mutable_RandomAccessIterator</code> concept checking template. In
general, the Boost concept checking classes expose associated types as
nested member typedefs so that you can use this syntax, which mimics the
approach used in the concept support proposed for the next version of
C++.</p>
<h4>Example</h4>
<h4>Multi-Type Concepts</h4>
<p>
Getting back to the earlier <a
href="./concept_check.htm#motivating-example">motivating example</a>,
one good applicatino of concept checks would be to insert
<tt>function_requires()</tt> at the top of <tt>std::stable_sort()</tt>
to make sure the template parameter type models <a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
RandomAccessIterator</a>. In addition, <tt>std::stable_sort()</tt>
requires that the <tt>value_type</tt> of the iterators be
<a href="http://www.sgi.com/tech/stl/LessThanComparable.html">
LessThanComparable</a>, so we also use <tt>function_requires()</tt> to
check this.
<pre>
template &lt;class RandomAccessIter&gt;
void stable_sort(RandomAccessIter first, RandomAccessIter last)
{
function_requires&lt; RandomAccessIteratorConcept&lt;RandomAccessIter&gt; &gt;();
typedef typename std::iterator_traits&lt;RandomAccessIter&gt;::value_type value_type;
function_requires&lt; LessThanComparableConcept&lt;value_type&gt; &gt;();
...
}
<p>Some concepts deal with more than one type. In this case the
corresponding concept checking class will have multiple template
parameters. The following example shows how <tt>BOOST_CONCEPT_REQUIRES</tt>
is used with the <a href=
"../property_map/doc/ReadWritePropertyMap.html">ReadWritePropertyMap</a>
concept, which takes two type parameters: a property map and the key type
for the map.</p>
<pre>
template &lt;class G, class Buffer, class BFSVisitor,
class ColorMap&gt;
BOOST_CONCEPT_REQUIRES(
((ReadWritePropertyMap&lt;ColorMap, typename IncidenceGraph&lt;G&gt;::vertex_descriptor&gt;)),
(void)) <font color="green">// return type</font>
breadth_first_search(G&amp; g,
typename graph_traits&lt;IncidenceGraph&gt;::vertex_descriptor s,
Buffer&amp; Q, BFSVisitor vis, ColorMap color)
{
typedef typename IncidenceGraph&lt;G&gt;::vertex_descriptor Vertex;
...
}
</pre>
<!-- There are a few places where the SGI STL documentation differs
from the corresponding requirements described in the C++ Standard. In
these cases we use the definition from the C++ Standard. -->
<p>
Some concepts deal with more than one type. In this case the
corresponding concept checking class will have multiple template
parameters. The following example shows how
<tt>function_requires()</tt> is used with the <a
href="../property_map/ReadWritePropertyMap.html">ReadWritePropertyMap</a>
concept which takes two type parameters: a property map and the key
type for the map.
<pre>
template &lt;class IncidenceGraph, class Buffer, class BFSVisitor,
class ColorMap&gt;
void breadth_first_search(IncidenceGraph& g,
typename graph_traits&lt;IncidenceGraph&gt;::vertex_descriptor s,
Buffer& Q, BFSVisitor vis, ColorMap color)
{
typedef typename graph_traits&lt;IncidenceGraph&gt;::vertex_descriptor Vertex;
function_requires&lt; ReadWritePropertyMap&lt;ColorMap, Vertex&gt; &gt;();
...
}
<p>Although concept checks are designed for use by generic library
implementors, they can also be useful to end users. Sometimes one may not
be sure whether some type models a particular concept. The syntactic
requirements, at least, can easily be checked by creating a small program
and using <tt>BOOST_CONCEPT_ASSERT</tt> with the type and concept in
question. For example:</p>
<pre>
<font color=
"green">// Make sure list&lt;int&gt; has bidirectional iterators.</font>
BOOST_CONCEPT_ASSERT((BidirectionalIterator&lt;std::list&lt;int&gt;::iterator&gt;));
</pre>
<p><a href="./concept_check.htm">Prev: Concept Checking
Introduction</a><br />
<a href="./creating_concepts.htm">Next: Creating Concept Checking
Classes</a><br /></p>
<hr />
As an example of using <tt>BOOST_CLASS_REQUIRE</tt> we look at a concept
check that could be added to <tt>std::vector</tt>. One requirement
that is placed on the element type is that it must be <a
href="http://www.sgi.com/tech/stl/Assignable.html">Assignable</a>.
We can check this by inserting
<tt>class_requires&lt;AssignableConcept&lt;T&gt; &gt;</tt> at the top
of the definition for <tt>std::vector</tt>.
<table>
<tr valign="top">
<td nowrap="nowrap">Copyright &copy; 2000</td>
<pre>
namespace std {
template &lt;class T&gt;
struct vector {
BOOST_CLASS_REQUIRE(T, boost, AssignableConcept);
...
};
}
</pre>
Although the concept checks are designed for use by generic library
implementors, they can also be useful to end users. Sometimes one may
not be sure whether some type models a particular concept. This can
easily be checked by creating a small program and using
<tt>function_requires()</tt> with the type and concept in question.
The file <a
href="./stl_concept_check.cpp"><tt>stl_concept_checks.cpp</tt></a>
gives and example of applying the concept checks to STL containers.
<p>
<a href="./concept_check.htm">Prev: Concept Checking Introduction</a> <br>
<a href="./creating_concepts.htm">Next: Creating Concept Checking Classes</a>
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
</TD></TR></TABLE>
</BODY>
</HTML>
<td><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
"mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>), 2007
<a href="mailto:dave@boost-consulting.com">David Abrahams</a>.</td>
</tr>
</table>
</body>
</html>