diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/boost/libs/concept_check | |
parent | Initial commit. (diff) | |
download | ceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.tar.xz ceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/concept_check')
32 files changed, 3382 insertions, 0 deletions
diff --git a/src/boost/libs/concept_check/CMakeLists.txt b/src/boost/libs/concept_check/CMakeLists.txt new file mode 100644 index 000000000..0cc25427c --- /dev/null +++ b/src/boost/libs/concept_check/CMakeLists.txt @@ -0,0 +1,21 @@ +# 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) + +cmake_minimum_required(VERSION 3.5) + +project(BoostConceptCheck 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) diff --git a/src/boost/libs/concept_check/Jamfile b/src/boost/libs/concept_check/Jamfile new file mode 100644 index 000000000..04e53d770 --- /dev/null +++ b/src/boost/libs/concept_check/Jamfile @@ -0,0 +1,10 @@ +# 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) + +# please order by name to ease maintenance +build-project test ; diff --git a/src/boost/libs/concept_check/LICENSE b/src/boost/libs/concept_check/LICENSE new file mode 100644 index 000000000..36b7cd93c --- /dev/null +++ b/src/boost/libs/concept_check/LICENSE @@ -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. diff --git a/src/boost/libs/concept_check/README.md b/src/boost/libs/concept_check/README.md new file mode 100644 index 000000000..6e1738ce2 --- /dev/null +++ b/src/boost/libs/concept_check/README.md @@ -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 | Travis | Appveyor | Coverity Scan | codecov.io | Deps | Docs | Tests | +:-------------: | ------ | -------- | ------------- | ---------- | ---- | ---- | ----- | +[`master`](https://github.com/boostorg/concept_check/tree/master) | [![Build Status](https://travis-ci.org/boostorg/concept_check.svg?branch=master)](https://travis-ci.org/boostorg/concept_check) | [![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-master-brightgreen.svg)](http://www.boost.org/doc/libs/master/doc/html/concept_check.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://travis-ci.org/boostorg/concept_check.svg?branch=develop)](https://travis-ci.org/boostorg/concept_check) | [![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)](http://www.boost.org/doc/libs/develop/doc/html/concept_check.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. + diff --git a/src/boost/libs/concept_check/bad_error_eg.cpp b/src/boost/libs/concept_check/bad_error_eg.cpp new file mode 100644 index 000000000..5f8d892d5 --- /dev/null +++ b/src/boost/libs/concept_check/bad_error_eg.cpp @@ -0,0 +1,14 @@ +#include <vector> +#include <complex> +#include "algorithm" + +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) diff --git a/src/boost/libs/concept_check/bibliography.htm b/src/boost/libs/concept_check/bibliography.htm new file mode 100644 index 000000000..4fcc8fe14 --- /dev/null +++ b/src/boost/libs/concept_check/bibliography.htm @@ -0,0 +1,65 @@ +<HTML> +<!-- 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 Concept Checking Library: Bibliography</Title> +<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b" + ALINK="#ff0000"> +<IMG SRC="../../boost.png" + 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. 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 © 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>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>) +</TD></TR></TABLE> + +</BODY> +</HTML> diff --git a/src/boost/libs/concept_check/concept_check.htm b/src/boost/libs/concept_check/concept_check.htm new file mode 100644 index 000000000..fc385dce4 --- /dev/null +++ b/src/boost/libs/concept_check/concept_check.htm @@ -0,0 +1,330 @@ +<!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="../../boost.png" alt="C++ Boost" width="277" height= + "86" /><br clear="none" /> + + <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" 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 “<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> + + <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 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 documented concept requirements may be too stringent, requiring + more than is really needed by the template.</li> + + <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 on template parameters + at their point of use.</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 suite of concept checking classes and archetype classes that match + the concept requirements in the C++ Standard Library.</li> + + <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><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> + + <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> + + <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>: +<font color="gray">1</font> #include <vector> +<font color="gray">2</font color="gray"> #include <complex> +<font color="gray">3</font color="gray"> #include <algorithm> +<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<std::complex<float> > v; +<font color="gray">8</font color="gray"> std::stable_sort(v.begin(), v.end()); +<font color="gray">9</font color="gray"> } +</pre> + + <p>Here, the <tt>std::stable_sort()</tt> algorithm is prototyped as + follows:</p> + <pre> + template <class RandomAccessIterator> + void stable_sort(RandomAccessIterator first, RandomAccessIterator last); +</pre> + + <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<std::complex<float + >*, std::vector<std::complex<float>, std::allocator<std::complex< + float> > > >]’: +/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<std::complex<float>*, std::vector<std::complex< + float>, std::allocator<std::complex<float> > > >]’ +/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<std::complex<float + >*, std::vector<std::complex<float>, std::allocator<std::complex< + float> > > >]’ +bad_error_eg.cpp:8: instantiated from here +/usr/include/c++/4.1.2/bits/stl_algo.h:2277: error: no match for + ‘operator<’ in ‘__val < __first. __gnu_cxx::__normal_iterator< + _Iterator, _Container>::operator* [with _Iterator = std::complex<float + >*, _Container = std::vector<std::complex<float>, std::allocator< + std::complex<float> > >]()’ +</pre> + + <p>In this case, the fundamental error is + that <tt>std:complex<float></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>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>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> + + <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> + + <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<TT>::~ + LessThanComparable() [with TT = std::complex<float>]’: +boost/concept/detail/general.hpp:29: instantiated from ‘static void boost:: + concepts::requirement<Model>::failed() [with Model = boost:: + LessThanComparable<std::complex<float> >]’ +boost/concept/requires.hpp:30: instantiated from ‘boost::_requires_<void + (*)(boost::LessThanComparable<std::complex<float> >)>’ +bad_error_eg.cpp:8: instantiated from here +boost/concept_check.hpp:236: error: no match for ‘operator<’ in ‘((boost:: + LessThanComparable<std::complex<float> >*)this)->boost:: + LessThanComparable<std::complex<float> >::a < ((boost:: + LessThanComparable<std::complex<float> >*)this)->boost:: + LessThanComparable<std::complex<float> >::b’ +</pre> + + <p>This message rectifies several of the shortcomings of the standard error + messages.</p> + + <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> + + <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> + + <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="history" id="history">History</a></h2> + + <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="publications" id="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" 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&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><br /></p> + <hr /> + + <table> + <tr valign="top"> + <td nowrap="nowrap">Copyright © 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> diff --git a/src/boost/libs/concept_check/concept_covering.htm b/src/boost/libs/concept_check/concept_covering.htm new file mode 100644 index 000000000..061f0f643 --- /dev/null +++ b/src/boost/libs/concept_check/concept_covering.htm @@ -0,0 +1,125 @@ +<!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) 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" /> + + <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> + +<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" /> + + <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&</tt> or <tt>const T&</tt>. That means it would be a mistake + to use <tt>T&</tt> or <tt>const T&</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 <class T> +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&() 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; } +}; +</pre> + + <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.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< + sgi_assignable_archetype<> > ValueType; + random_access_iterator_archetype<ValueType> ri; + std::stable_sort(ri, ri); +} +</pre> + + <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 /> + + <table> + <tr valign="top"> + <td nowrap="nowrap">Copyright © 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> diff --git a/src/boost/libs/concept_check/creating_concepts.htm b/src/boost/libs/concept_check/creating_concepts.htm new file mode 100644 index 000000000..bb56e8c2c --- /dev/null +++ b/src/boost/libs/concept_check/creating_concepts.htm @@ -0,0 +1,157 @@ +<!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) 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" /> + + <title>Creating Concept Checking Classes</title> + <link rel="stylesheet" href="../../rst.css" type="text/css" /> +</head> + +<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" /> + + <h2><a name="creating-concept-checks" id="creating-concept-checks">Creating + Concept Checking Classes</a></h2> + + <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 <class X> +struct InputIterator + : Assignable<X>, EqualityComparable<X> +{ + private: + typedef std::iterator_traits<X> 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; + + BOOST_CONCEPT_ASSERT((SignedInteger<difference_type>)); + BOOST_CONCEPT_ASSERT((Convertible<iterator_category, std::input_iterator_tag>)); + + 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& x = ++j; <font color= +"green">// require preincrement returning X&</font> + } + + private: + X i; + value_type v; + + <font color= +"green">// Type deduction will fail unless the arguments have the same type.</font> + template <typename T> + void same_type(T const&, T const&); +}; +</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& x = ++j; <font color= +"green">// require preincrement returning X&</font> +} +</pre> + + <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>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> + + <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> + + <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 © 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> diff --git a/src/boost/libs/concept_check/implementation.htm b/src/boost/libs/concept_check/implementation.htm new file mode 100644 index 000000000..e9db3bf65 --- /dev/null +++ b/src/boost/libs/concept_check/implementation.htm @@ -0,0 +1,205 @@ +<!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) 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" /> + + <title>Concept Checking Implementation</title> +</head> + +<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" /> + + <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&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 <class RandomAccessIterator> + void stable_sort_constraints(RandomAccessIterator i) + { + typename std::iterator_traits<RandomAccessIterator> + ::difference_type n; + i += n; // exercise the requirements for RandomAccessIterator + ... + } + template <class RandomAccessIterator> + void stable_sort(RandomAccessIterator first, RandomAccessIterator last) + { + typedef void (*fptr_type)(RandomAccessIterator); + fptr_type x = &stable_sort_constraints; + ... + } +</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 <class Iter> + struct RandomAccessIteratorConcept + { + void constraints() + { + i += n; + ... + } + typename std::iterator_traits<RandomAccessIterator> + ::difference_type n; + Iter i; + ... + }; +</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 <class Iter> + void stable_sort(Iter first, Iter last) + { + function_requires< RandomAccessIteratorConcept<Iter> >(); + ... + } +</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 <class Concept> + void function_requires() + { + void (Concept::*x)() = BOOST_FPTR Concept::constraints; + ignore_unused_variable_warning(x); + } +</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 <type_var>::* func##type_var##concept)(); \ + template <func##type_var##concept _Tp1> \ + struct concept_checking_##type_var##concept { }; \ + typedef concept_checking_##type_var##concept< \ + BOOST_FPTR ns::concept<type_var>::constraints> \ + concept_checking_typedef_##type_var##concept +</pre> + + <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 +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 <class Concept> + class class_requires + { + typedef void (Concept::* function_pointer)(); + + template <function_pointer Fptr> + struct dummy_struct { }; + public: + typedef dummy_struct< BOOST_FPTR Concept::constraints > 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. + +--></p> + + <p><a href="./reference.htm">Next: Reference</a><br /> + <a href="prog_with_concepts.htm">Prev: Programming With + Concepts</a><br /></p> + <hr /> + + <table> + <tr valign="top"> + <td nowrap="nowrap">Copyright © 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> diff --git a/src/boost/libs/concept_check/index.html b/src/boost/libs/concept_check/index.html new file mode 100644 index 000000000..36fea491f --- /dev/null +++ b/src/boost/libs/concept_check/index.html @@ -0,0 +1,13 @@ +<html> +<head> +<meta http-equiv="refresh" content="0; URL=concept_check.htm"> +</head> +<body> +Automatic redirection failed, please go to +<a href="concept_check.htm">concept_check.htm</a>. <hr> +<p> 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>
\ No newline at end of file diff --git a/src/boost/libs/concept_check/meta/explicit-failures-markup.xml b/src/boost/libs/concept_check/meta/explicit-failures-markup.xml new file mode 100644 index 000000000..0d933e6ab --- /dev/null +++ b/src/boost/libs/concept_check/meta/explicit-failures-markup.xml @@ -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> diff --git a/src/boost/libs/concept_check/meta/libraries.json b/src/boost/libs/concept_check/meta/libraries.json new file mode 100644 index 000000000..480b9c842 --- /dev/null +++ b/src/boost/libs/concept_check/meta/libraries.json @@ -0,0 +1,15 @@ +{ + "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>" + ] +} diff --git a/src/boost/libs/concept_check/prog_with_concepts.htm b/src/boost/libs/concept_check/prog_with_concepts.htm new file mode 100644 index 000000000..f78a40c29 --- /dev/null +++ b/src/boost/libs/concept_check/prog_with_concepts.htm @@ -0,0 +1,144 @@ +<!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) 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" /> + + <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> + +<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" /> + + <h2><a name="programming-with-concepts" id= + "programming-with-concepts">Programming with Concepts</a></h2> + + <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><b>Requirement Minimization Principle:</b> Minimize the requirements on + the input parameters of a component to increase its reusability.</p> + + <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> +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.boost.org/sgi/stl/LessThanComparable.html"> +LessThanComparable</a>, which not only +includes <tt>operator<()</tt>, but also <tt>operator>()</tt>, +<tt>operator<=()</tt>, and <tt>operator>=()</tt>. +It turns out that <tt>std::stable_sort()</tt> only uses +<tt>operator<()</tt>. The question then arises: should +<tt>std::stable_sort()</tt> be specified in terms of the concept +<a +href="http://www.boost.org/sgi/stl/LessThanComparable.html"> +LessThanComparable</a> or in terms of a concept that only +requires <tt>operator<()</tt>? + +<p> +We remark first that the use of <a +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<()</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.boost.org/sgi/stl/LessThanComparable.html"> +LessThanComparable</a> does not violate the requirement minimization +principle because all of the comparison operators (<tt><</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.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.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><br /></p> + <hr /> + + <table> + <tr valign="top"> + <td nowrap="nowrap">Copyright © 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> diff --git a/src/boost/libs/concept_check/reference.htm b/src/boost/libs/concept_check/reference.htm new file mode 100644 index 000000000..efb3f6138 --- /dev/null +++ b/src/boost/libs/concept_check/reference.htm @@ -0,0 +1,418 @@ +<!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) 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=utf-8" /> + <link rel="stylesheet" href="../../rst.css" type="text/css" /> + + <title>Boost Concept Checking Reference</title> +</head> + +<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" /> + + <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> + + <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> +#include "boost/concept/requires.hpp" + +<font color="gray">template <…<em>template parameters</em>…></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> + + <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> + + <h3><a name="basic-concepts" id="basic-concepts">Basic Concept Checking + Classes</a></h3> + <pre> +#include "boost/concept_check.hpp" + +template <class T> +struct Integer; // Is T a built-in integer type? + +template <class T> +struct SignedInteger; // Is T a built-in signed integer type? + +template <class T> +struct UnsignedInteger; // Is T a built-in unsigned integer type? + +template <class X, class Y> +struct Convertible; // Is X convertible to Y? + +template <class T> +struct <a href= +"../utility/Assignable.html">Assignable</a>; // Standard ref 23.1 + +template <class T> +struct SGI<a href= +"http://www.boost.org/sgi/stl/Assignable.html">Assignable</a>; + +template <class T> +struct <a href= +"http://www.boost.org/sgi/stl/DefaultConstructible.html">DefaultConstructible</a>; + +template <class T> +struct <a href= +"../utility/CopyConstructible.html">CopyConstructible</a>; // Standard ref 20.1.3 + +template <class T> +struct <a href= +"http://www.boost.org/sgi/stl/EqualityComparable.html">EqualityComparable</a>; // Standard ref 20.1.1 + +template <class T> +struct <a href= +"../utility/LessThanComparable.html">LessThanComparable</a>; // Standard ref 20.1.2 + +template <class T> +struct Comparable; // The SGI STL <a href= +"http://www.boost.org/sgi/stl/LessThanComparable.html">LessThanComparable</a> concept +</pre> + + <h3><a name="iterator-concepts" id="iterator-concepts">Iterator Concept + Checking Classes</a></h3> + <pre> +template <class Iter> +struct <a href= +"http://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a>; // Standard ref 24.1.1 Table 72 + +template <class Iter, class T> +struct <a href= +"http://www.boost.org/sgi/stl/OutputIterator.html">OutputIterator</a>; // Standard ref 24.1.2 Table 73 + +template <class Iter> +struct <a href= +"http://www.boost.org/sgi/stl/ForwardIterator.html">ForwardIterator</a>; // Standard ref 24.1.3 Table 74 + +template <class Iter> +struct Mutable_ForwardIterator; + +template <class Iter> +struct <a href= +"http://www.boost.org/sgi/stl/BidirectionalIterator.html">BidirectionalIterator</a>; // Standard ref 24.1.4 Table 75 + +template <class Iter> +struct Mutable_BidirectionalIterator; + +template <class Iter> +struct <a href= +"http://www.boost.org/sgi/stl/RandomAccessIterator.html">RandomAccessIterator</a>; // Standard ref 24.1.5 Table 76 + +template <class Iter> +struct Mutable_RandomAccessIterator; +</pre> + + <h3><a name="function-object-concepts" id= + "function-object-concepts">Function Object Concept Checking + Classes</a></h3> + <pre> +#include "boost/concept_check.hpp" + +template <class Func, class Return> +struct <a href="http://www.boost.org/sgi/stl/Generator.html">Generator</a>; + +template <class Func, class Return, class Arg> +struct <a href= +"http://www.boost.org/sgi/stl/UnaryFunction.html">UnaryFunction</a>; + +template <class Func, class Return, class First, class Second> +struct <a href= +"http://www.boost.org/sgi/stl/BinaryFunction.html">BinaryFunction</a>; + +template <class Func, class Arg> +struct Unary<a href= +"http://www.boost.org/sgi/stl/Predicate.html">Predicate</a>; + +template <class Func, class First, class Second> +struct <a href= +"http://www.boost.org/sgi/stl/BinaryPredicate.html">BinaryPredicate</a>; + +template <class Func, class First, class Second> +struct Const_BinaryPredicate; + +template <class Func, class Return> +struct <a href= +"http://www.boost.org/sgi/stl/AdaptableGenerator.html">AdaptableGenerator</a>; + +template <class Func, class Return, class Arg> +struct <a href= +"http://www.boost.org/sgi/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>; + +template <class Func, class First, class Second> +struct <a href= +"http://www.boost.org/sgi/stl/AdaptableBinaryFunction.html">AdaptableBinaryFunction</a>; + +template <class Func, class Arg> +struct <a href= +"http://www.boost.org/sgi/stl/AdaptablePredicate.html">AdaptablePredicate</a>; + +template <class Func, class First, class Second> +struct <a href= +"http://www.boost.org/sgi/stl/AdaptableBinaryPredicate.html">AdaptableBinaryPredicate</a>; +</pre> + + <h3><a name="container-concepts" id="container-concepts">Container Concept + Checking Classes</a></h3> + <pre> +#include "boost/concept_check.hpp" + +template <class C> +struct <a href= +"http://www.boost.org/sgi/stl/Container.html">Container</a>; // Standard ref 23.1 Table 65 + +template <class C> +struct Mutable_Container; + +template <class C> +struct <a href= +"http://www.boost.org/sgi/stl/ForwardContainer.html">ForwardContainer</a>; + +template <class C> +struct Mutable_ForwardContainer; + +template <class C> +struct <a href= +"http://www.boost.org/sgi/stl/ReversibleContainer.html">ReversibleContainer</a>; // Standard ref 23.1 Table 66 + +template <class C> +struct Mutable_ReversibleContainer; + +template <class C> +struct <a href= +"http://www.boost.org/sgi/stl/RandomAccessContainer.html">RandomAccessContainer</a>; + +template <class C> +struct Mutable_RandomAccessContainer; + +template <class C> +struct <a href= +"http://www.boost.org/sgi/stl/Sequence.html">Sequence</a>; // Standard ref 23.1.1 + +template <class C> +struct <a href= +"http://www.boost.org/sgi/stl/FrontInsertionSequence.html">FrontInsertionSequence</a>; + +template <class C> +struct <a href= +"http://www.boost.org/sgi/stl/BackInsertionSequence.html">BackInsertionSequence</a>; + +template <class C> +struct <a href= +"http://www.boost.org/sgi/stl/AssociativeContainer.html">AssociativeContainer</a>; // Standard ref 23.1.2 Table 69 + +template <class C> +struct <a href= +"http://www.boost.org/sgi/stl/UniqueAssociativeContainer.html">UniqueAssociativeContainer</a>; + +template <class C> +struct <a href= +"http://www.boost.org/sgi/stl/MultipleAssociativeContainer.html">MultipleAssociativeContainer</a>; + +template <class C> +struct <a href= +"http://www.boost.org/sgi/stl/SimpleAssociativeContainer.html">SimpleAssociativeContainer</a>; + +template <class C> +struct <a href= +"http://www.boost.org/sgi/stl/PairAssociativeContainer.html">PairAssociativeContainer</a>; + +template <class C> +struct <a href= +"http://www.boost.org/sgi/stl/SortedAssociativeContainer.html">SortedAssociativeContainer</a>; + +template <class C> +struct <a href= +"../utility/Collection.html">Collection</a>; +</pre> + + <h3><a name="basic-archetype" id="basic-archetype">Basic Archetype + Classes</a></h3> + <pre> +#include "boost/concept_archetype.hpp" + +template <class T = int> +class null_archetype; // A type that models no concepts. + +template <class Base = null_archetype> +class default_constructible_archetype; + +template <class Base = null_archetype> +class assignable_archetype; + +template <class Base = null_archetype> +class copy_constructible_archetype; + +template <class Base = null_archetype> +class equality_comparable_archetype; + +template <class T, class Base = null_archetype> +class convertible_to_archetype; +</pre> + + <h3><a name="iterator-archetype" id="iterator-archetype">Iterator Archetype + Classes</a></h3> + <pre> +#include "boost/concept_archetype.hpp" + +template <class ValueType> +class trivial_iterator_archetype; + +template <class ValueType> +class mutable_trivial_iterator_archetype; + +template <class ValueType> +class input_iterator_archetype; + +template <class ValueType> +class forward_iterator_archetype; + +template <class ValueType> +class bidirectional_iterator_archetype; + +template <class ValueType> +class random_access_iterator_archetype; +</pre> + + <h3><a name="function-object-archetype" id= + "function-object-archetype">Function Object Archetype Classes</a></h3> + <pre> +#include "boost/concept_archetype.hpp" + +template <class Arg, class Return> +class unary_function_archetype; + +template <class Arg1, class Arg2, class Return> +class binary_function_archetype; + +template <class Arg> +class predicate_archetype; + +template <class Arg1, class Arg2> +class binary_predicate_archetype; +</pre> + + <h3><a name="container-archetype" id="container-archetype">Container + Archetype Classes</a></h3> + <pre> +UNDER CONSTRUCTION +</pre> + + <h3><a name="deprecated-functions" id="deprecated-functions">Deprecated + Functions</a></h3> + <pre> +#include "boost/concept_check.hpp" + +template <class Concept> +void function_requires(); +</pre> + + <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 "boost/concept/assert.hpp"</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 © 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> diff --git a/src/boost/libs/concept_check/test/Jamfile.v2 b/src/boost/libs/concept_check/test/Jamfile.v2 new file mode 100644 index 000000000..4510302b7 --- /dev/null +++ b/src/boost/libs/concept_check/test/Jamfile.v2 @@ -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 ] + ; + diff --git a/src/boost/libs/concept_check/test/class_concept_check_test.cpp b/src/boost/libs/concept_check/test/class_concept_check_test.cpp new file mode 100644 index 000000000..d5512c64f --- /dev/null +++ b/src/boost/libs/concept_check/test/class_concept_check_test.cpp @@ -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; +} diff --git a/src/boost/libs/concept_check/test/class_concept_fail_expected.cpp b/src/boost/libs/concept_check/test/class_concept_fail_expected.cpp new file mode 100644 index 000000000..74268e36e --- /dev/null +++ b/src/boost/libs/concept_check/test/class_concept_fail_expected.cpp @@ -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; +} diff --git a/src/boost/libs/concept_check/test/concept_check_fail_expected.cpp b/src/boost/libs/concept_check/test/concept_check_fail_expected.cpp new file mode 100644 index 000000000..15bfe7a82 --- /dev/null +++ b/src/boost/libs/concept_check/test/concept_check_fail_expected.cpp @@ -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; +} diff --git a/src/boost/libs/concept_check/test/concept_check_test.cpp b/src/boost/libs/concept_check/test/concept_check_test.cpp new file mode 100644 index 000000000..f39ced781 --- /dev/null +++ b/src/boost/libs/concept_check/test/concept_check_test.cpp @@ -0,0 +1,177 @@ +// (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> + +/* + + This file verifies that function_requires() of the Boost Concept + Checking Library does not cause errors when it is 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< DefaultConstructible<foo> >(); + } + { + typedef assignable_archetype<> foo; + function_requires< Assignable<foo> >(); + } + { + typedef copy_constructible_archetype<> foo; + function_requires< CopyConstructible<foo> >(); + } + { + typedef sgi_assignable_archetype<> foo; + function_requires< SGIAssignable<foo> >(); + } + { + typedef copy_constructible_archetype<> foo; + typedef convertible_to_archetype<foo> convertible_to_foo; + function_requires< Convertible<convertible_to_foo, foo> >(); + } + { + function_requires< Convertible<boolean_archetype, bool> >(); + } + { + typedef equality_comparable_archetype<> foo; + function_requires< EqualityComparable<foo> >(); + } + { + typedef less_than_comparable_archetype<> foo; + function_requires< LessThanComparable<foo> >(); + } + { + typedef comparable_archetype<> foo; + function_requires< Comparable<foo> >(); + } + { + typedef equal_op_first_archetype<> First; + typedef equal_op_second_archetype<> Second; + function_requires< EqualOp<First, Second> >(); + } + { + typedef not_equal_op_first_archetype<> First; + typedef not_equal_op_second_archetype<> Second; + function_requires< NotEqualOp<First, Second> >(); + } + { + typedef less_than_op_first_archetype<> First; + typedef less_than_op_second_archetype<> Second; + function_requires< LessThanOp<First, Second> >(); + } + { + typedef less_equal_op_first_archetype<> First; + typedef less_equal_op_second_archetype<> Second; + function_requires< LessEqualOp<First, Second> >(); + } + { + typedef greater_than_op_first_archetype<> First; + typedef greater_than_op_second_archetype<> Second; + function_requires< GreaterThanOp<First, Second> >(); + } + { + typedef greater_equal_op_first_archetype<> First; + typedef greater_equal_op_second_archetype<> 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< PlusOp<Return, First, Second> >(); + } + + //=========================================================================== + // Function Object Concepts + + { + typedef generator_archetype<null_archetype<> > foo; + function_requires< Generator<foo, null_archetype<> > >(); + } +#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + { + function_requires< Generator< void_generator_archetype, void > >(); + } +#endif + { + typedef unary_function_archetype<int, int> F; + function_requires< UnaryFunction<F, int, int> >(); + } + { + typedef binary_function_archetype<int, int, int> F; + function_requires< BinaryFunction<F, int, int, int> >(); + } + { + typedef unary_predicate_archetype<int> F; + function_requires< UnaryPredicate<F, int> >(); + } + { + typedef binary_predicate_archetype<int, int> F; + function_requires< BinaryPredicate<F, int, int> >(); + } + + //=========================================================================== + // Iterator Concepts + { + typedef input_iterator_archetype<null_archetype<> > Iter; + function_requires< InputIterator<Iter> >(); + } + { + typedef output_iterator_archetype<int> Iter; + 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< ForwardIterator<Iter> >(); + } + { + typedef mutable_forward_iterator_archetype<assignable_archetype<> > Iter; + function_requires< Mutable_ForwardIterator<Iter> >(); + } + { + typedef bidirectional_iterator_archetype<null_archetype<> > Iter; + function_requires< BidirectionalIterator<Iter> >(); + } + { + typedef mutable_bidirectional_iterator_archetype<assignable_archetype<> > + Iter; + function_requires< Mutable_BidirectionalIterator<Iter> >(); + } + { + typedef random_access_iterator_archetype<null_archetype<> > Iter; + function_requires< RandomAccessIterator<Iter> >(); + } + { + typedef mutable_random_access_iterator_archetype<assignable_archetype<> > + Iter; + function_requires< Mutable_RandomAccessIterator<Iter> >(); + } + + //=========================================================================== + // Container Concepts + + // UNDER CONSTRUCTION + + return 0; +} diff --git a/src/boost/libs/concept_check/test/fake_sort.hpp b/src/boost/libs/concept_check/test/fake_sort.hpp new file mode 100644 index 000000000..99c75465a --- /dev/null +++ b/src/boost/libs/concept_check/test/fake_sort.hpp @@ -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 <boost/detail/iterator.hpp> +# 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 diff --git a/src/boost/libs/concept_check/test/function_requires_fail.cpp b/src/boost/libs/concept_check/test/function_requires_fail.cpp new file mode 100644 index 000000000..03beaecc8 --- /dev/null +++ b/src/boost/libs/concept_check/test/function_requires_fail.cpp @@ -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; +} diff --git a/src/boost/libs/concept_check/test/old_concept_class_fail.cpp b/src/boost/libs/concept_check/test/old_concept_class_fail.cpp new file mode 100644 index 000000000..be41037fa --- /dev/null +++ b/src/boost/libs/concept_check/test/old_concept_class_fail.cpp @@ -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; +} diff --git a/src/boost/libs/concept_check/test/old_concept_function_fail.cpp b/src/boost/libs/concept_check/test/old_concept_function_fail.cpp new file mode 100644 index 000000000..6b7bf30a3 --- /dev/null +++ b/src/boost/libs/concept_check/test/old_concept_function_fail.cpp @@ -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; +} diff --git a/src/boost/libs/concept_check/test/old_concept_pass.cpp b/src/boost/libs/concept_check/test/old_concept_pass.cpp new file mode 100644 index 000000000..e9601fc24 --- /dev/null +++ b/src/boost/libs/concept_check/test/old_concept_pass.cpp @@ -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; +} diff --git a/src/boost/libs/concept_check/test/old_concepts.hpp b/src/boost/libs/concept_check/test/old_concepts.hpp new file mode 100644 index 000000000..76fad3c64 --- /dev/null +++ b/src/boost/libs/concept_check/test/old_concepts.hpp @@ -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 diff --git a/src/boost/libs/concept_check/test/stl_concept_check.cpp b/src/boost/libs/concept_check/test/stl_concept_check.cpp new file mode 100644 index 000000000..d336de1c0 --- /dev/null +++ b/src/boost/libs/concept_check/test/stl_concept_check.cpp @@ -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; +} diff --git a/src/boost/libs/concept_check/test/stl_concept_covering.cpp b/src/boost/libs/concept_check/test/stl_concept_covering.cpp new file mode 100644 index 000000000..220294276 --- /dev/null +++ b/src/boost/libs/concept_check/test/stl_concept_covering.cpp @@ -0,0 +1,950 @@ +// (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 <algorithm> +#include <numeric> +#include <boost/config.hpp> +#include <boost/concept_check.hpp> +#include <boost/concept_archetype.hpp> + +/* + + This file uses the archetype classes to find out which concepts + actually *cover* the STL algorithms true requirements. The + archetypes/concepts chosen do not necessarily match the C++ standard + or the SGI STL documentation, but instead were chosen based on the + minimal concepts that current STL implementations require, which in + many cases is less stringent than the standard. In some places there + was significant differences in the implementations' requirements and + in those places macros were used to select different requirements, + the purpose being to document what the requirements of various + implementations are. It is an open issue as to whether the C++ + standard should be changed to reflect these weaker requirements. + +*/ + +/** + * 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. +// It is mutually convertible, and also SGIAssignable +template <class T> +class mutually_convertible_archetype +{ +private: + mutually_convertible_archetype() { } +public: + mutually_convertible_archetype(const mutually_convertible_archetype&) { } + mutually_convertible_archetype& + operator=(const mutually_convertible_archetype&) + { return *this; } + mutually_convertible_archetype(boost::detail::dummy_constructor) { } + + template <class U> + mutually_convertible_archetype& + operator=(const mutually_convertible_archetype<U>&) + { return *this; } + +}; + + +// for std::accumulate +namespace accum +{ + typedef boost::sgi_assignable_archetype<> Ret; + struct T { + T(const Ret&) { } + T(boost::detail::dummy_constructor x) { } + }; + typedef boost::null_archetype<> Tin; + Ret operator+(const T&, const Tin&) { + return Ret(dummy_cons); + } +} + +// 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 +{ + typedef boost::sgi_assignable_archetype<> RetAdd; + typedef boost::sgi_assignable_archetype<> RetMult; + struct T { + T(const RetAdd&) { } + T(boost::detail::dummy_constructor x) { } + }; + typedef boost::null_archetype<int> Tin1; + typedef boost::null_archetype<char> Tin2; +} + +namespace boost { // so Koenig lookup will find + + inner_prod::RetMult + operator*(const inner_prod::Tin1&, const inner_prod::Tin2&) { + return inner_prod::RetMult(dummy_cons); + } + inner_prod::RetAdd + operator+(const inner_prod::T&, + const inner_prod::RetMult&) { + return inner_prod::RetAdd(dummy_cons); + } +} + + +// for std::partial_sum and adj_diff +namespace part_sum +{ + class T { + public: + typedef boost::sgi_assignable_archetype<> Ret; + T(const Ret&) { } + T(boost::detail::dummy_constructor x) { } + private: + T() { } + }; + T::Ret operator+(const T&, const T&) { + return T::Ret(dummy_cons); + } + T::Ret operator-(const T&, const T&) { + return T::Ret(dummy_cons); + } +} + +// for std::power + +namespace power_stuff { + struct monoid_archetype { + monoid_archetype(boost::detail::dummy_constructor x) { } + }; + + boost::multipliable_archetype<monoid_archetype> + identity_element + (std::multiplies< boost::multipliable_archetype<monoid_archetype> >) + { + return boost::multipliable_archetype<monoid_archetype>(dummy_cons); + } +} + +struct tag1 { }; +struct tag2 { }; + + +int +main() +{ + using namespace boost; + + //=========================================================================== + // Non-mutating Algorithms + { + 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; + BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE< Left > in; + equality_comparable2_second_archetype<> value(dummy_cons); + in = std::find(in, in, value); + } + { + typedef null_archetype<> T; + input_iterator_archetype<T> in; + unary_predicate_archetype<T> pred(dummy_cons); + in = std::find_if(in, in, pred); + } + { + forward_iterator_archetype< equality_comparable_archetype<> > fo; + fo = std::adjacent_find(fo, fo); + } + { + forward_iterator_archetype< + convertible_to_archetype< null_archetype<> > > fo; + binary_predicate_archetype<null_archetype<> , null_archetype<> > + pred(dummy_cons); + fo = std::adjacent_find(fo, fo, pred); + } + // gcc bug + { + typedef equal_op_first_archetype<> Left; + 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 BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Left> InIter; + InIter in; + 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< 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 BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Left> InIter1; + InIter1 in1; + typedef equal_op_second_archetype<> Right; + 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<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; + BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Left> in1; + typedef equality_comparable2_second_archetype<> Right; + BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Right> in2; + bool b = std::equal(in1, in1, in2); + ignore_unused_variable_warning(b); + } + { + input_iterator_archetype< null_archetype<> > + in1, in2; + binary_predicate_archetype<null_archetype<> , null_archetype<> > + pred(dummy_cons); + bool b = std::equal(in1, in1, in2, pred); + ignore_unused_variable_warning(b); + } + { + typedef equality_comparable2_first_archetype<> Left; + forward_iterator_archetype<Left> fo1; + typedef equality_comparable2_second_archetype<> Right; + forward_iterator_archetype<Right> fo2; + fo1 = std::search(fo1, fo1, fo2, fo2); + } + { + typedef equality_comparable2_first_archetype< + convertible_to_archetype<null_archetype<> > > Left; + forward_iterator_archetype<Left> fo1; + typedef equality_comparable2_second_archetype< + convertible_to_archetype<null_archetype<> > > Right; + forward_iterator_archetype<Right> fo2; + binary_predicate_archetype<null_archetype<> , null_archetype<> > + pred(dummy_cons); + fo1 = std::search(fo1, fo1, fo2, fo2, pred); + } + { + typedef equality_comparable2_first_archetype<> Left; + forward_iterator_archetype<Left> fo; + equality_comparable2_second_archetype<> value(dummy_cons); + int n = 1; + fo = std::search_n(fo, fo, n, value); + } + { + forward_iterator_archetype< + convertible_to_archetype<null_archetype<> > > fo; + convertible_to_archetype<null_archetype<> > value(dummy_cons); + binary_predicate_archetype<null_archetype<> , null_archetype<> > + pred(dummy_cons); + int n = 1; + fo = std::search_n(fo, fo, n, value, pred); + } + { + typedef equality_comparable2_first_archetype<> Left; + forward_iterator_archetype<Left> fo1; + typedef equality_comparable2_second_archetype<null_archetype<> > Right; + forward_iterator_archetype<Right> fo2; + fo1 = std::find_end(fo1, fo1, fo2, fo2); + } + { + // equality comparable required because find_end() calls search + typedef equality_comparable2_first_archetype< + convertible_to_archetype<null_archetype<> > > Left; + forward_iterator_archetype<Left> fo1; + typedef equality_comparable2_second_archetype< + convertible_to_archetype<null_archetype<> > > Right; + forward_iterator_archetype<Right> fo2; + binary_predicate_archetype<null_archetype<> , null_archetype<> > + pred(dummy_cons); + fo1 = std::find_end(fo1, fo1, fo2, fo2, pred); + } + + //=========================================================================== + // Mutating Algorithms + + { + typedef null_archetype<> T; + input_iterator_archetype<T> in; + output_iterator_archetype<T> out(dummy_cons); + out = std::copy(in, in, out); + } + { + typedef assignable_archetype<> OutT; + typedef convertible_to_archetype<OutT> InT; + bidirectional_iterator_archetype<InT> bid_in; + mutable_bidirectional_iterator_archetype<OutT> bid_out; + bid_out = std::copy_backward(bid_in, bid_in, bid_out); + } + { + sgi_assignable_archetype<> a(dummy_cons), b(dummy_cons); + std::swap(a, b); + } + { + typedef sgi_assignable_archetype<> T; + 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 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<> , + convertible_to_archetype<Tout> > op(dummy_cons); + out = std::transform(in, in, out, op); + } + { + 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<Tin1, Tin2, + convertible_to_archetype<Tout> > op(dummy_cons); + out = std::transform(in1, in1, in2, out, op); + } + { + typedef equality_comparable2_first_archetype< + assignable_archetype<> > FT; + mutable_forward_iterator_archetype<FT> fi; + equality_comparable2_second_archetype< + convertible_to_archetype<FT> > value(dummy_cons); + std::replace(fi, fi, value, value); + } + { + typedef null_archetype<> PredArg; + typedef assignable_archetype< + convertible_to_archetype<PredArg> > FT; + mutable_forward_iterator_archetype<FT> fi; + unary_predicate_archetype<PredArg> pred(dummy_cons); + convertible_to_archetype<FT> value(dummy_cons); + std::replace_if(fi, fi, pred, value); + } +#if !defined(BOOST_MSVC) || BOOST_WORKAROUND(BOOST_MSVC, > 1900) + // fails on MSVC 2015 and earlier + { + // 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; + 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); + } + { + // The issue of ?: also affects this function + 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<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; + typedef convertible_to_archetype<FT> T; + 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; + output_iterator_archetype<Tout> out(dummy_cons); + T value(dummy_cons); + int n = 1; + out = std::fill_n(out, n, value); + } +#endif + { + typedef assignable_archetype<> FT; + typedef convertible_to_archetype<FT> Ret; + mutable_forward_iterator_archetype<FT> fi; + generator_archetype<Ret> gen; + std::generate(fi, fi, gen); + } + { + typedef assignable_archetype<> FT; + typedef convertible_to_archetype<FT> Ret; + mutable_forward_iterator_archetype<FT> fi; + generator_archetype<Ret> gen; + int n = 1; + std::generate_n(fi, n, gen); + } + { + typedef assignable_archetype< equality_comparable2_first_archetype<> > FT; + typedef equality_comparable2_second_archetype<> T; + mutable_forward_iterator_archetype<FT> fi; + T value(dummy_cons); + fi = std::remove(fi, fi, value); + } + { + typedef assignable_archetype<> FT; + mutable_forward_iterator_archetype<FT> fi; + typedef null_archetype<> PredArg; + 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; + 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<> 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); + } + { + typedef sgi_assignable_archetype< equality_comparable_archetype<> > T; + mutable_forward_iterator_archetype<T> fi; + fi = std::unique(fi, fi); + } + { + typedef null_archetype<int> Arg1; + typedef null_archetype<char> Arg2; + typedef sgi_assignable_archetype< + convertible_to_archetype<Arg1, + convertible_to_archetype<Arg2> > > FT; + mutable_forward_iterator_archetype<FT> fi; + binary_predicate_archetype<Arg1, Arg2> pred(dummy_cons); + fi = std::unique(fi, fi, pred); + } + // gcc bug + { + typedef equality_comparable_archetype< sgi_assignable_archetype<> > T; + BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<T> in; + output_iterator_archetype<T> out(dummy_cons); + out = std::unique_copy(in, in, out); + } + { + 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); + } + { + typedef sgi_assignable_archetype<> T; + mutable_bidirectional_iterator_archetype<T> bi; + std::reverse(bi, bi); + } + { + typedef null_archetype<> Tout; + typedef convertible_to_archetype<Tout> Tin; + bidirectional_iterator_archetype<Tin> bi; + output_iterator_archetype<Tout> out(dummy_cons); + out = std::reverse_copy(bi, bi, out); + } + { + typedef sgi_assignable_archetype<> T; + mutable_forward_iterator_archetype<T> fi; + // Issue, SGI STL is not have void return type, C++ standard does + std::rotate(fi, fi, fi); + } + { + typedef null_archetype<> Tout; + typedef convertible_to_archetype<Tout> FT; + forward_iterator_archetype<FT> fi; + 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; + std::random_shuffle(ri, ri); + } + { + typedef sgi_assignable_archetype<> T; + mutable_random_access_iterator_archetype<T> ri; + 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; + mutable_bidirectional_iterator_archetype<FT> bi; + unary_predicate_archetype<PredArg> pred(dummy_cons); + bi = std::partition(bi, bi, pred); + } +#ifndef BOOST_MSVC + { + // fails on MSVC + 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 + { + typedef sgi_assignable_archetype< + less_than_comparable_archetype<> > T; + mutable_random_access_iterator_archetype<T> ri; + std::sort(ri, ri); + } + { + typedef null_archetype<> Arg; + typedef sgi_assignable_archetype< + convertible_to_archetype<Arg> > T; + mutable_random_access_iterator_archetype<T> ri; + binary_predicate_archetype<Arg, Arg> comp(dummy_cons); + std::sort(ri, ri, comp); + } + { + typedef less_than_comparable_archetype< + sgi_assignable_archetype<> > ValueType; + mutable_random_access_iterator_archetype<ValueType> ri; + std::stable_sort(ri, ri); + } + { + typedef null_archetype<> Arg; + typedef sgi_assignable_archetype< + convertible_to_archetype<Arg> > ValueType; + mutable_random_access_iterator_archetype<ValueType> ri; + binary_predicate_archetype<Arg, Arg> comp(dummy_cons); + std::stable_sort(ri, ri, comp); + } + { + typedef sgi_assignable_archetype< + less_than_comparable_archetype<> > T; + mutable_random_access_iterator_archetype<T> ri; + std::partial_sort(ri, ri, ri); + } + + { + typedef null_archetype<> Arg; + typedef sgi_assignable_archetype< + convertible_to_archetype<Arg> > T; + mutable_random_access_iterator_archetype<T> ri; + 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; + 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 sgi_assignable_archetype<> T; + input_iterator_archetype<T> in; + mutable_random_access_iterator_archetype<T> ri_out; + binary_predicate_archetype<T, T> comp(dummy_cons); + ri_out = std::partial_sort_copy(in, in , ri_out, ri_out, comp); + } + { + typedef sgi_assignable_archetype< less_than_comparable_archetype<> > T; + mutable_random_access_iterator_archetype<T> ri; + std::nth_element(ri, ri, ri); + } + { + typedef null_archetype<int> Arg1; + typedef null_archetype<char> Arg2; + typedef sgi_assignable_archetype< + convertible_to_archetype<Arg1, + convertible_to_archetype<Arg2> > > T; + mutable_random_access_iterator_archetype<T> ri; + binary_predicate_archetype<Arg1, Arg2> comp(dummy_cons); + std::nth_element(ri, ri, ri, comp); + } + { +#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); + fi = std::lower_bound(fi, fi, value); + } + { + typedef null_archetype<int> Arg1; + typedef null_archetype<char> Arg2; + typedef convertible_to_archetype<Arg1> FT; + typedef convertible_to_archetype<Arg2> T; + forward_iterator_archetype<FT> fi; + T value(dummy_cons); + binary_predicate_archetype<Arg1, Arg2> comp(dummy_cons); + fi = std::lower_bound(fi, fi, value, comp); + } + { +#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; +#endif + forward_iterator_archetype<FT> fi; + T value(dummy_cons); + fi = std::upper_bound(fi, fi, value); + } + { + typedef null_archetype<int> Arg1; + typedef null_archetype<char> Arg2; + // Note, order of T,FT is flipped from lower_bound + typedef convertible_to_archetype<Arg1> T; + typedef convertible_to_archetype<Arg2> FT; + forward_iterator_archetype<FT> fi; + T value(dummy_cons); + 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(__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; +#endif + typedef forward_iterator_archetype<FT> FIter; + FIter fi; + T value(dummy_cons); + 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; + typedef convertible_to_archetype<Arg1, + convertible_to_archetype<Arg2> > FT; + typedef convertible_to_archetype<Arg2, + convertible_to_archetype<Arg1> > T; + typedef forward_iterator_archetype<FT> FIter; + FIter fi; + T value(dummy_cons); + binary_predicate_archetype<Arg1, Arg2> comp(dummy_cons); + std::pair<FIter,FIter> p = std::equal_range(fi, fi, value, comp); + ignore_unused_variable_warning(p); + } + { +#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; +#endif + forward_iterator_archetype<FT> fi; + T value(dummy_cons); + bool b = std::binary_search(fi, fi, value); + ignore_unused_variable_warning(b); + } + { + typedef null_archetype<int> Arg1; + typedef null_archetype<char> Arg2; + typedef convertible_to_archetype<Arg1, + convertible_to_archetype<Arg2> > FT; + typedef convertible_to_archetype<Arg2, + convertible_to_archetype<Arg1> > T; + typedef forward_iterator_archetype<FT> FIter; + FIter fi; + T value(dummy_cons); + binary_predicate_archetype<Arg1, Arg2> comp(dummy_cons); + bool b = std::binary_search(fi, fi, value, comp); + ignore_unused_variable_warning(b); + } + { + typedef null_archetype<> Tout; + 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; + // 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); + out = std::set_intersection(in1, in1, in2, in2, out); + out = std::set_difference(in1, in1, in2, in2, out); + out = std::set_symmetric_difference(in1, in1, in2, in2, out); + } + { + 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); + out = std::set_difference(in1, in1, in2, in2, out, comp); + out = std::set_symmetric_difference(in1, in1, in2, in2, out, comp); + } + { + typedef sgi_assignable_archetype< + less_than_comparable_archetype<> > T; + mutable_bidirectional_iterator_archetype<T> bi; + std::inplace_merge(bi, bi, bi); + } + { + typedef null_archetype<> Arg; + typedef sgi_assignable_archetype< + convertible_to_archetype<Arg> > T; + mutable_bidirectional_iterator_archetype<T> bi; + binary_predicate_archetype<Arg, Arg> comp(dummy_cons); + std::inplace_merge(bi, bi, bi, comp); + } + // gcc bug + { + 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; + 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> 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); + } + { + typedef sgi_assignable_archetype< + less_than_comparable_archetype<> > T; + mutable_random_access_iterator_archetype<T> ri; + std::push_heap(ri, ri); + std::pop_heap(ri, ri); + std::make_heap(ri, ri); + std::sort_heap(ri, ri); + } + { + typedef null_archetype<> Arg; + typedef sgi_assignable_archetype< + convertible_to_archetype<Arg> > T; + mutable_random_access_iterator_archetype<T> ri; + binary_predicate_archetype<Arg, Arg> comp(dummy_cons); + std::push_heap(ri, ri, comp); + std::pop_heap(ri, ri, comp); + std::make_heap(ri, ri, comp); + std::sort_heap(ri, ri, comp); + } + { + typedef less_than_comparable_archetype<> T; + T a(dummy_cons), b(dummy_cons); + 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); + } + { + typedef null_archetype<> Arg; + binary_predicate_archetype<Arg, Arg> comp(dummy_cons); + typedef convertible_to_archetype<Arg> T; + T a(dummy_cons), b(dummy_cons); + 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); + } + { + typedef less_than_comparable_archetype<> T; + forward_iterator_archetype<T> fi; + fi = std::min_element(fi, fi); + fi = std::max_element(fi, fi); + } + { + typedef null_archetype<> Arg; + binary_predicate_archetype<Arg, Arg> comp(dummy_cons); + typedef convertible_to_archetype<Arg> T; + forward_iterator_archetype<T> fi; + fi = std::min_element(fi, fi, comp); + fi = std::max_element(fi, fi, comp); + } + { + typedef sgi_assignable_archetype< + less_than_comparable_archetype<> > T; + mutable_bidirectional_iterator_archetype<T> bi; + bool b = std::next_permutation(bi, bi); + b = std::prev_permutation(bi, bi); + ignore_unused_variable_warning(b); + } + { + typedef null_archetype<> Arg; + binary_predicate_archetype<Arg, Arg> comp(dummy_cons); + typedef sgi_assignable_archetype< + convertible_to_archetype<Arg> > T; + mutable_bidirectional_iterator_archetype<T> bi; + bool b = std::next_permutation(bi, bi, comp); + b = std::prev_permutation(bi, bi, comp); + ignore_unused_variable_warning(b); + } + //=========================================================================== + // Generalized Numeric Algorithms + + { + // Bummer, couldn't use plus_op because of a problem with + // mutually recursive types. + input_iterator_archetype<accum::Tin> in; + accum::T init(dummy_cons); + init = std::accumulate(in, in, init); + } + { + typedef null_archetype<int> Arg1; + typedef null_archetype<char> Arg2; + typedef sgi_assignable_archetype< + convertible_to_archetype<Arg1> > T; + typedef convertible_to_archetype<T> Ret; + 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); + } + { + input_iterator_archetype<inner_prod::Tin1> in1; + input_iterator_archetype<inner_prod::Tin2> in2; + inner_prod::T init(dummy_cons); + init = std::inner_product(in1, in1, in2, init); + } + { + typedef null_archetype<int> MultArg1; + typedef null_archetype<char> MultArg2; + typedef null_archetype<short> AddArg1; + typedef null_archetype<long> AddArg2; + typedef sgi_assignable_archetype< + convertible_to_archetype<AddArg1> > T; + typedef convertible_to_archetype<AddArg2> RetMult; + typedef convertible_to_archetype<T> RetAdd; + 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::T> in; + output_iterator_archetype<part_sum::T> out(dummy_cons); + out = std::partial_sum(in, in, out); + } + { + 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<T, T, T> subtract_op(dummy_cons); + out = std::adjacent_difference(in, in, out, subtract_op); + } + { + 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; +} diff --git a/src/boost/libs/concept_check/test/usage_fail.cpp b/src/boost/libs/concept_check/test/usage_fail.cpp new file mode 100644 index 000000000..39b1060ff --- /dev/null +++ b/src/boost/libs/concept_check/test/usage_fail.cpp @@ -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; + + + diff --git a/src/boost/libs/concept_check/test/where.cpp b/src/boost/libs/concept_check/test/where.cpp new file mode 100644 index 000000000..dfbfd020f --- /dev/null +++ b/src/boost/libs/concept_check/test/where.cpp @@ -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; +} diff --git a/src/boost/libs/concept_check/test/where_fail.cpp b/src/boost/libs/concept_check/test/where_fail.cpp new file mode 100644 index 000000000..e56b40fed --- /dev/null +++ b/src/boost/libs/concept_check/test/where_fail.cpp @@ -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; +} diff --git a/src/boost/libs/concept_check/using_concept_check.htm b/src/boost/libs/concept_check/using_concept_check.htm new file mode 100644 index 000000000..59bb419c3 --- /dev/null +++ b/src/boost/libs/concept_check/using_concept_check.htm @@ -0,0 +1,186 @@ +<!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) 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" /> + + <title>Using Concept Checks</title> + <link rel="stylesheet" href="../../rst.css" type="text/css" /> +</head> + +<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" /> + + <h2><a name="using-concept-checks" id="using-concept-checks">Using Concept + Checks</a></h2> + + <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 <class T> +struct EqualityComparable; +</pre> + + <p>The template argument is the type to be checked. That is, the purpose of + <tt>EqualityComparable<<em>T</em>></tt> is to make sure that + <tt><em>T</em></tt> models the EqualityComparable concept.</p> + + <h4><tt>BOOST_CONCEPT_ASSERT()</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 <class T> +void generic_library_function(T x) +{ + BOOST_CONCEPT_ASSERT<strong>((</strong>EqualityComparable<T><strong>))</strong>; + <font color="green">// ...</font> +}; + +template <class It> +class generic_library_class +{ + BOOST_CONCEPT_ASSERT<strong>((</strong>RandomAccessIterator<It><strong>))</strong>; + <font color="green">// ...</font> +}; + +<font color="green">// In the user's code:</font> +class foo { + <font color="green">//... </font> +}; + +int main() { + foo x; + generic_library_function(x); + generic_library_class<std::vector<char>::iterator> y; + <font color="green">//...</font> +} +</pre> + + <h4><tt>BOOST_CONCEPT_REQUIRES</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> + + <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 <class RanIter> +BOOST_CONCEPT_REQUIRES( + ((Mutable_RandomAccessIterator<RanIter>)) + ((LessThanComparable<typename Mutable_RandomAccessIterator<RanIter>::value_type>)), + (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>Multi-Type Concepts</h4> + + <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 <class G, class Buffer, class BFSVisitor, + class ColorMap> +BOOST_CONCEPT_REQUIRES( + ((ReadWritePropertyMap<ColorMap, typename IncidenceGraph<G>::vertex_descriptor>)), + (void)) <font color="green">// return type</font> +breadth_first_search(G& g, + typename graph_traits<IncidenceGraph>::vertex_descriptor s, + Buffer& Q, BFSVisitor vis, ColorMap color) +{ + typedef typename IncidenceGraph<G>::vertex_descriptor Vertex; + ... +} +</pre> + + <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<int> has bidirectional iterators.</font> +BOOST_CONCEPT_ASSERT((BidirectionalIterator<std::list<int>::iterator>)); +</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 /> + + <table> + <tr valign="top"> + <td nowrap="nowrap">Copyright © 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> |