mirror of
https://github.com/boostorg/functional.git
synced 2025-08-02 14:04:27 +02:00
This commit was manufactured by cvs2svn to create branch
'boost-graph-library'. [SVN r7698]
This commit is contained in:
96
.gitattributes
vendored
Normal file
96
.gitattributes
vendored
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
* text=auto !eol svneol=native#text/plain
|
||||||
|
*.gitattributes text svneol=native#text/plain
|
||||||
|
|
||||||
|
# Scriptish formats
|
||||||
|
*.bat text svneol=native#text/plain
|
||||||
|
*.bsh text svneol=native#text/x-beanshell
|
||||||
|
*.cgi text svneol=native#text/plain
|
||||||
|
*.cmd text svneol=native#text/plain
|
||||||
|
*.js text svneol=native#text/javascript
|
||||||
|
*.php text svneol=native#text/x-php
|
||||||
|
*.pl text svneol=native#text/x-perl
|
||||||
|
*.pm text svneol=native#text/x-perl
|
||||||
|
*.py text svneol=native#text/x-python
|
||||||
|
*.sh eol=lf svneol=LF#text/x-sh
|
||||||
|
configure eol=lf svneol=LF#text/x-sh
|
||||||
|
|
||||||
|
# Image formats
|
||||||
|
*.bmp binary svneol=unset#image/bmp
|
||||||
|
*.gif binary svneol=unset#image/gif
|
||||||
|
*.ico binary svneol=unset#image/ico
|
||||||
|
*.jpeg binary svneol=unset#image/jpeg
|
||||||
|
*.jpg binary svneol=unset#image/jpeg
|
||||||
|
*.png binary svneol=unset#image/png
|
||||||
|
*.tif binary svneol=unset#image/tiff
|
||||||
|
*.tiff binary svneol=unset#image/tiff
|
||||||
|
*.svg text svneol=native#image/svg%2Bxml
|
||||||
|
|
||||||
|
# Data formats
|
||||||
|
*.pdf binary svneol=unset#application/pdf
|
||||||
|
*.avi binary svneol=unset#video/avi
|
||||||
|
*.doc binary svneol=unset#application/msword
|
||||||
|
*.dsp text svneol=crlf#text/plain
|
||||||
|
*.dsw text svneol=crlf#text/plain
|
||||||
|
*.eps binary svneol=unset#application/postscript
|
||||||
|
*.gz binary svneol=unset#application/gzip
|
||||||
|
*.mov binary svneol=unset#video/quicktime
|
||||||
|
*.mp3 binary svneol=unset#audio/mpeg
|
||||||
|
*.ppt binary svneol=unset#application/vnd.ms-powerpoint
|
||||||
|
*.ps binary svneol=unset#application/postscript
|
||||||
|
*.psd binary svneol=unset#application/photoshop
|
||||||
|
*.rdf binary svneol=unset#text/rdf
|
||||||
|
*.rss text svneol=unset#text/xml
|
||||||
|
*.rtf binary svneol=unset#text/rtf
|
||||||
|
*.sln text svneol=native#text/plain
|
||||||
|
*.swf binary svneol=unset#application/x-shockwave-flash
|
||||||
|
*.tgz binary svneol=unset#application/gzip
|
||||||
|
*.vcproj text svneol=native#text/xml
|
||||||
|
*.vcxproj text svneol=native#text/xml
|
||||||
|
*.vsprops text svneol=native#text/xml
|
||||||
|
*.wav binary svneol=unset#audio/wav
|
||||||
|
*.xls binary svneol=unset#application/vnd.ms-excel
|
||||||
|
*.zip binary svneol=unset#application/zip
|
||||||
|
|
||||||
|
# Text formats
|
||||||
|
.htaccess text svneol=native#text/plain
|
||||||
|
*.bbk text svneol=native#text/xml
|
||||||
|
*.cmake text svneol=native#text/plain
|
||||||
|
*.css text svneol=native#text/css
|
||||||
|
*.dtd text svneol=native#text/xml
|
||||||
|
*.htm text svneol=native#text/html
|
||||||
|
*.html text svneol=native#text/html
|
||||||
|
*.ini text svneol=native#text/plain
|
||||||
|
*.log text svneol=native#text/plain
|
||||||
|
*.mak text svneol=native#text/plain
|
||||||
|
*.qbk text svneol=native#text/plain
|
||||||
|
*.rst text svneol=native#text/plain
|
||||||
|
*.sql text svneol=native#text/x-sql
|
||||||
|
*.txt text svneol=native#text/plain
|
||||||
|
*.xhtml text svneol=native#text/xhtml%2Bxml
|
||||||
|
*.xml text svneol=native#text/xml
|
||||||
|
*.xsd text svneol=native#text/xml
|
||||||
|
*.xsl text svneol=native#text/xml
|
||||||
|
*.xslt text svneol=native#text/xml
|
||||||
|
*.xul text svneol=native#text/xul
|
||||||
|
*.yml text svneol=native#text/plain
|
||||||
|
boost-no-inspect text svneol=native#text/plain
|
||||||
|
CHANGES text svneol=native#text/plain
|
||||||
|
COPYING text svneol=native#text/plain
|
||||||
|
INSTALL text svneol=native#text/plain
|
||||||
|
Jamfile text svneol=native#text/plain
|
||||||
|
Jamroot text svneol=native#text/plain
|
||||||
|
Jamfile.v2 text svneol=native#text/plain
|
||||||
|
Jamrules text svneol=native#text/plain
|
||||||
|
Makefile* text svneol=native#text/plain
|
||||||
|
README text svneol=native#text/plain
|
||||||
|
TODO text svneol=native#text/plain
|
||||||
|
|
||||||
|
# Code formats
|
||||||
|
*.c text svneol=native#text/plain
|
||||||
|
*.cpp text svneol=native#text/plain
|
||||||
|
*.h text svneol=native#text/plain
|
||||||
|
*.hpp text svneol=native#text/plain
|
||||||
|
*.ipp text svneol=native#text/plain
|
||||||
|
*.tpp text svneol=native#text/plain
|
||||||
|
*.jam text svneol=native#text/plain
|
||||||
|
*.java text svneol=native#text/plain
|
132
binders.html
Normal file
132
binders.html
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<title>Boost Function Object Adapter Library</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body bgcolor="#FFFFFF" text="#000000">
|
||||||
|
|
||||||
|
<table border="1" bgcolor="#007F7F" cellpadding="2">
|
||||||
|
<tr>
|
||||||
|
<td bgcolor="#FFFFFF"><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" WIDTH="277" HEIGHT="86"></td>
|
||||||
|
<td><a href="../../index.htm"><font face="Arial" color="#FFFFFF"><big>Home </big></font></a></td>
|
||||||
|
<td><a href="../../libraries.htm"><font face="Arial" color="#FFFFFF"><big>Libraries </big></font></a></td>
|
||||||
|
<td><a href="../../people.htm"><font face="Arial" color="#FFFFFF"><big>People </big></font></a></td>
|
||||||
|
<td><a href="../../more/faq.htm"><font face="Arial" color="#FFFFFF"><big>FAQ </big></font></a></td>
|
||||||
|
<td><a href="../../more/index.htm"><font face="Arial" color="#FFFFFF"><big>More </big></font></a></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h1>Binders</h1>
|
||||||
|
|
||||||
|
<p>The header <nobr><a
|
||||||
|
href="../../boost/functional.hpp">functional.hpp</a></nobr> provides
|
||||||
|
enhanced versions of both the binder function object adapters from the
|
||||||
|
C++ Standard Library <nobr>(§20.3.6):</nobr></p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><tt>binder1st</tt></li>
|
||||||
|
<li><tt>binder2nd</tt></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>As well as the corresponding helper functions</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><tt>bind1st</tt></li>
|
||||||
|
<li><tt>bind2nd</tt></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>The key benefit of these adapters over those in the Standard
|
||||||
|
Library is they avoid the problem of <a href="#refref">references to
|
||||||
|
references.</a>
|
||||||
|
|
||||||
|
<h3>Usage</h3>
|
||||||
|
|
||||||
|
<p>Usage is identical to the standard binders. For example,</p>
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
class Foo {
|
||||||
|
public:
|
||||||
|
void bar(std::ostream &);
|
||||||
|
// ...
|
||||||
|
};
|
||||||
|
// ...
|
||||||
|
std::vector<Foo> c;
|
||||||
|
// ...
|
||||||
|
std::for_each(c.begin(), c.end(),
|
||||||
|
boost::bind2nd(boost::mem_fun_ref(&Foo::bar), std::cout));
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<h3 id="refref">References to References</h3>
|
||||||
|
|
||||||
|
<p>Consider the usage example above</p>
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
class Foo {
|
||||||
|
public:
|
||||||
|
void bar(<strong>std::ostream &</strong>);
|
||||||
|
// ...
|
||||||
|
};
|
||||||
|
// ...
|
||||||
|
std::for_each(c.begin(), c.end(),
|
||||||
|
boost::bind2nd(boost::mem_fun_ref(&Foo::bar), std::cout));
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<p>If this had been written using <tt><nobr>std::bind2nd</nobr></tt>
|
||||||
|
and <tt><nobr>std::mem_fun_ref</nobr></tt>, it would be unlikely to
|
||||||
|
compile.</p>
|
||||||
|
|
||||||
|
<p>The problem arises because <tt><nobr>bar</nobr></tt> takes a
|
||||||
|
reference argument. The Standard defines
|
||||||
|
<tt><nobr>std::mem_fun_ref</nobr></tt> such that it creates a function
|
||||||
|
object whose <tt><nobr>second_argument_type</nobr></tt> will be
|
||||||
|
<tt><nobr>std::ostream&</nobr></tt>.</p>
|
||||||
|
|
||||||
|
<p>The call to <tt><nobr>bind2nd</nobr></tt> creates a
|
||||||
|
<tt><nobr>binder2nd</nobr></tt> which the Standard defines as follows:
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
template <class Operation>
|
||||||
|
class binder2nd
|
||||||
|
: public unary_function<typename Operation::first_argument_type,
|
||||||
|
typename Operation::result_type> {
|
||||||
|
...
|
||||||
|
public:
|
||||||
|
binder2nd(const Operation& x,
|
||||||
|
<strong>const typename Operation::second_argument_type& y</strong>);
|
||||||
|
...
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<p>Since our operation's <tt><nobr>second_argument_type</nobr></tt> is
|
||||||
|
<tt><nobr>std::ostream&</nobr></tt>, the type of <tt>y</tt> in the
|
||||||
|
constructor would be <tt><nobr>std::ostream&&</nobr></tt>. Since you
|
||||||
|
cannot have a reference to a reference, at this point we should get a
|
||||||
|
compilation error because references to references are illegal in C++
|
||||||
|
(but see <a
|
||||||
|
href="http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#106">
|
||||||
|
C++ Standard core language active issues list</a>).</p>
|
||||||
|
|
||||||
|
<p>The binders in this library avoid this problem by using the Boost
|
||||||
|
<nobr><tt><a
|
||||||
|
href="../utility/call_traits.htm">call_traits</a></tt></nobr> templates.</p>
|
||||||
|
|
||||||
|
<p>Our constructor is declared
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
binder2nd(const Operation& x,
|
||||||
|
<strong>typename call_traits<
|
||||||
|
typename binary_traits<Operation>::second_argument_type
|
||||||
|
>::param_type y</strong>)
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<p>As a result, <tt>y</tt> has a type of <tt><nobr>std::ostream&</nobr></tt>,
|
||||||
|
and our example compiles.</p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<p>Copyright © 2000 Cadenza New Zealand Ltd. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.</p>
|
||||||
|
|
||||||
|
<p>Revised 28 June 2000</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
257
function_test.cpp
Normal file
257
function_test.cpp
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
// Tests for the Boost functional.hpp header file
|
||||||
|
//
|
||||||
|
// Note that functional.hpp relies on partial specialisation to be
|
||||||
|
// effective. If your compiler lacks this feature, very few of the
|
||||||
|
// tests would compile, and so have been excluded from the test.
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2000
|
||||||
|
// Cadenza New Zealand Ltd
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, distribute and sell this software
|
||||||
|
// and its documentation for any purpose is hereby granted without
|
||||||
|
// fee, provided that the above copyright notice appears in all copies
|
||||||
|
// and that both the copyright notice and this permission notice
|
||||||
|
// appear in supporting documentation. Cadenza New Zealand Ltd makes
|
||||||
|
// no representations about the suitability of this software for any
|
||||||
|
// purpose. It is provided "as is" without express or implied
|
||||||
|
// warranty.
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
// $Id$
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
// $Log$
|
||||||
|
// Revision 1.1.1.1 2000/07/07 16:04:18 beman
|
||||||
|
// 1.16.1 initial CVS checkin
|
||||||
|
//
|
||||||
|
// Revision 1.3 2000/06/26 09:44:01 mark
|
||||||
|
// Updated following feedback from Jens Maurer.
|
||||||
|
//
|
||||||
|
// Revision 1.2 2000/05/17 08:31:45 mark
|
||||||
|
// Added extra tests now that function traits work correctly.
|
||||||
|
// For compilers with no support for partial specialisation,
|
||||||
|
// excluded tests that won't work.
|
||||||
|
//
|
||||||
|
// Revision 1.1 2000/05/07 09:14:41 mark
|
||||||
|
// Initial revision
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// To demonstrate what the boosted function object adapters do for
|
||||||
|
// you, try compiling with USE_STD defined. This will endeavour to
|
||||||
|
// use the standard function object adapters, but is likely to result
|
||||||
|
// in numerous errors due to the fact that you cannot have references
|
||||||
|
// to references.
|
||||||
|
#ifdef USE_STD
|
||||||
|
#include <functional>
|
||||||
|
#define boost std
|
||||||
|
#else
|
||||||
|
#include <boost/functional.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class Person
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Person() {}
|
||||||
|
Person(const char *n) : name(n) {}
|
||||||
|
|
||||||
|
const std::string &get_name() const { return name; }
|
||||||
|
void print(std::ostream &os) const { os << name << " "; }
|
||||||
|
void set_name(const std::string &n) { name = n; std::cout << name << " "; }
|
||||||
|
std::string clear_name() { std::string ret = name; name = ""; return ret; }
|
||||||
|
void do_something(int) const {}
|
||||||
|
|
||||||
|
bool is_fred() const { return name == "Fred"; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
bool is_equal(const std::string &s1, const std::string &s2)
|
||||||
|
{
|
||||||
|
return s1 == s2;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_betty(const std::string &s)
|
||||||
|
{
|
||||||
|
return s == "Betty";
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_set_name(Person *p, const std::string &name)
|
||||||
|
{
|
||||||
|
p->set_name(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_set_name_ref(Person &p, const std::string &name)
|
||||||
|
{
|
||||||
|
p.set_name(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::vector<Person> v1;
|
||||||
|
v1.push_back("Fred");
|
||||||
|
v1.push_back("Wilma");
|
||||||
|
v1.push_back("Barney");
|
||||||
|
v1.push_back("Betty");
|
||||||
|
|
||||||
|
const std::vector<Person> cv1(v1.begin(), v1.end());
|
||||||
|
|
||||||
|
std::vector<std::string> v2;
|
||||||
|
v2.push_back("Fred");
|
||||||
|
v2.push_back("Wilma");
|
||||||
|
v2.push_back("Barney");
|
||||||
|
v2.push_back("Betty");
|
||||||
|
|
||||||
|
Person person;
|
||||||
|
Person &r = person;
|
||||||
|
|
||||||
|
Person fred("Fred");
|
||||||
|
Person wilma("Wilma");
|
||||||
|
Person barney("Barney");
|
||||||
|
Person betty("Betty");
|
||||||
|
std::vector<Person*> v3;
|
||||||
|
v3.push_back(&fred);
|
||||||
|
v3.push_back(&wilma);
|
||||||
|
v3.push_back(&barney);
|
||||||
|
v3.push_back(&betty);
|
||||||
|
|
||||||
|
const std::vector<Person*> cv3(v3.begin(), v3.end());
|
||||||
|
std::vector<const Person*> v3c(v3.begin(), v3.end());
|
||||||
|
|
||||||
|
std::ostream &os = std::cout;
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
// unary_traits, unary_negate
|
||||||
|
std::transform(v2.begin(), v2.end(),
|
||||||
|
std::ostream_iterator<bool>(std::cout, " "),
|
||||||
|
boost::not1(is_betty));
|
||||||
|
|
||||||
|
std::cout << '\n';
|
||||||
|
std::transform(v1.begin(), v1.end(),
|
||||||
|
std::ostream_iterator<bool>(std::cout, " "),
|
||||||
|
boost::not1(boost::mem_fun_ref(&Person::is_fred)));
|
||||||
|
|
||||||
|
// binary_traits, binary_negate
|
||||||
|
std::cout << '\n';
|
||||||
|
std::transform(v2.begin(), v2.end(),
|
||||||
|
std::ostream_iterator<bool>(std::cout, " "),
|
||||||
|
boost::bind1st(boost::not2(is_equal), "Betty"));
|
||||||
|
|
||||||
|
std::cout << '\n';
|
||||||
|
std::transform(v2.begin(), v2.end(),
|
||||||
|
std::ostream_iterator<bool>(std::cout, " "),
|
||||||
|
boost::bind2nd(boost::not2(is_equal), "Betty"));
|
||||||
|
|
||||||
|
// pointer_to_unary_function
|
||||||
|
std::cout << '\n';
|
||||||
|
std::transform(v2.begin(), v2.end(),
|
||||||
|
std::ostream_iterator<bool>(std::cout, " "),
|
||||||
|
boost::not1(boost::ptr_fun(is_betty)));
|
||||||
|
|
||||||
|
// binary_traits, bind1st, bind2nd
|
||||||
|
std::cout << '\n';
|
||||||
|
std::transform(v2.begin(), v2.end(),
|
||||||
|
std::ostream_iterator<bool>(std::cout, " "),
|
||||||
|
boost::bind1st(is_equal, "Betty"));
|
||||||
|
|
||||||
|
std::cout << '\n';
|
||||||
|
std::transform(v2.begin(), v2.end(),
|
||||||
|
std::ostream_iterator<bool>(std::cout, " "),
|
||||||
|
boost::bind2nd(is_equal, "Betty"));
|
||||||
|
|
||||||
|
// pointer_to_binary_function, bind1st
|
||||||
|
std::cout << '\n';
|
||||||
|
std::for_each(v2.begin(), v2.end(), boost::bind1st(boost::ptr_fun(do_set_name), &person));
|
||||||
|
|
||||||
|
std::cout << '\n';
|
||||||
|
std::for_each(v2.begin(), v2.end(), boost::bind1st(boost::ptr_fun(do_set_name_ref), person));
|
||||||
|
|
||||||
|
std::cout << '\n';
|
||||||
|
std::for_each(v2.begin(), v2.end(), boost::bind1st(boost::ptr_fun(do_set_name_ref), r));
|
||||||
|
|
||||||
|
// binary_traits
|
||||||
|
std::cout << '\n';
|
||||||
|
std::for_each(v2.begin(), v2.end(), boost::bind1st(do_set_name, &person));
|
||||||
|
|
||||||
|
std::cout << '\n';
|
||||||
|
std::for_each(v2.begin(), v2.end(), boost::bind1st(do_set_name_ref, person));
|
||||||
|
|
||||||
|
std::cout << '\n';
|
||||||
|
std::for_each(v2.begin(), v2.end(), boost::bind1st(do_set_name_ref, r));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// const_mem_fun_t
|
||||||
|
std::cout << '\n';
|
||||||
|
std::transform(v3.begin(), v3.end(),
|
||||||
|
std::ostream_iterator<std::string>(std::cout, " "),
|
||||||
|
boost::mem_fun(&Person::get_name));
|
||||||
|
|
||||||
|
std::cout << '\n';
|
||||||
|
std::transform(cv3.begin(), cv3.end(),
|
||||||
|
std::ostream_iterator<std::string>(std::cout, " "),
|
||||||
|
boost::mem_fun(&Person::get_name));
|
||||||
|
|
||||||
|
std::cout << '\n';
|
||||||
|
std::transform(v3c.begin(), v3c.end(),
|
||||||
|
std::ostream_iterator<std::string>(std::cout, " "),
|
||||||
|
boost::mem_fun(&Person::get_name));
|
||||||
|
|
||||||
|
// const_mem_fun_ref_t
|
||||||
|
std::cout << '\n';
|
||||||
|
std::transform(v1.begin(), v1.end(),
|
||||||
|
std::ostream_iterator<std::string>(std::cout, " "),
|
||||||
|
boost::mem_fun_ref(&Person::get_name));
|
||||||
|
|
||||||
|
std::cout << '\n';
|
||||||
|
std::transform(cv1.begin(), cv1.end(),
|
||||||
|
std::ostream_iterator<std::string>(std::cout, " "),
|
||||||
|
boost::mem_fun_ref(&Person::get_name));
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
// const_mem_fun1_t, bind2nd
|
||||||
|
std::cout << '\n';
|
||||||
|
std::for_each(v3.begin(), v3.end(), boost::bind2nd(boost::mem_fun(&Person::print), std::cout));
|
||||||
|
|
||||||
|
std::cout << '\n';
|
||||||
|
std::for_each(v3.begin(), v3.end(), boost::bind2nd(boost::mem_fun(&Person::print), os));
|
||||||
|
|
||||||
|
// const_mem_fun1_ref_t, bind2nd
|
||||||
|
std::cout << '\n';
|
||||||
|
std::for_each(v1.begin(), v1.end(), boost::bind2nd(boost::mem_fun_ref(&Person::print), std::cout));
|
||||||
|
|
||||||
|
std::cout << '\n';
|
||||||
|
std::for_each(v1.begin(), v1.end(), boost::bind2nd(boost::mem_fun_ref(&Person::print), os));
|
||||||
|
|
||||||
|
// mem_fun1_t, bind1st
|
||||||
|
std::cout << '\n';
|
||||||
|
std::for_each(v2.begin(), v2.end(), boost::bind1st(boost::mem_fun(&Person::set_name), &person));
|
||||||
|
|
||||||
|
// mem_fun1_ref_t, bind1st
|
||||||
|
std::cout << '\n';
|
||||||
|
std::for_each(v2.begin(), v2.end(), boost::bind1st(boost::mem_fun_ref(&Person::set_name), person));
|
||||||
|
|
||||||
|
std::cout << '\n';
|
||||||
|
std::for_each(v2.begin(), v2.end(), boost::bind1st(boost::mem_fun_ref(&Person::set_name), r));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// mem_fun_t
|
||||||
|
std::cout << '\n';
|
||||||
|
std::transform(v3.begin(), v3.end(), std::ostream_iterator<std::string>(std::cout, " "),
|
||||||
|
boost::mem_fun(&Person::clear_name));
|
||||||
|
|
||||||
|
// mem_fun_ref_t
|
||||||
|
std::cout << '\n';
|
||||||
|
std::transform(v1.begin(), v1.end(), std::ostream_iterator<std::string>(std::cout, " "),
|
||||||
|
boost::mem_fun_ref(&Person::clear_name));
|
||||||
|
|
||||||
|
std::cout << '\n';
|
||||||
|
return 0;
|
||||||
|
}
|
196
function_traits.html
Normal file
196
function_traits.html
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<title>Boost Function Object Adapter Library</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body bgcolor="#FFFFFF" text="#000000">
|
||||||
|
|
||||||
|
<table border="1" bgcolor="#007F7F" cellpadding="2">
|
||||||
|
<tr>
|
||||||
|
<td bgcolor="#FFFFFF"><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" WIDTH="277" HEIGHT="86"></td>
|
||||||
|
<td><a href="../../index.htm"><font face="Arial" color="#FFFFFF"><big>Home </big></font></a></td>
|
||||||
|
<td><a href="../../libraries.htm"><font face="Arial" color="#FFFFFF"><big>Libraries </big></font></a></td>
|
||||||
|
<td><a href="../../people.htm"><font face="Arial" color="#FFFFFF"><big>People </big></font></a></td>
|
||||||
|
<td><a href="../../more/faq.htm"><font face="Arial" color="#FFFFFF"><big>FAQ </big></font></a></td>
|
||||||
|
<td><a href="../../more/index.htm"><font face="Arial" color="#FFFFFF"><big>More </big></font></a></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h1>Function Object Traits</h1>
|
||||||
|
|
||||||
|
<p>The header <nobr><a
|
||||||
|
href="../../boost/functional.hpp">functional.hpp</a></nobr> provides two
|
||||||
|
traits class templates for functions and function objects:</p>
|
||||||
|
|
||||||
|
<table border="1">
|
||||||
|
<tr>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Contents</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" rowspan="4"><tt><nobr>template <typename T></nobr><br><nobr>struct unary_traits<nobr></tt>
|
||||||
|
</td>
|
||||||
|
<td valign="top"><tt><nobr>function_type</nobr></tt>
|
||||||
|
</td>
|
||||||
|
<td valign="top">The type of the function or function object itself (i.e., <tt>T</tt>).
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><tt><nobr>param_type</nobr></tt>
|
||||||
|
</td>
|
||||||
|
<td valign="top">The type that should be used to pass the function or function object as a parameter.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><tt><nobr>result_type</nobr></tt>
|
||||||
|
</td>
|
||||||
|
<td valign="top">The type returned by the function or function object.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><tt><nobr>argument_type</nobr></tt>
|
||||||
|
</td>
|
||||||
|
<td valign="top">The type of the argument to the function or function object.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" rowspan="5"><tt><nobr>template <typename T></nobr><br><nobr>struct binary_traits<nobr></tt>
|
||||||
|
</td>
|
||||||
|
<td valign="top"><tt><nobr>function_type</nobr></tt>
|
||||||
|
</td>
|
||||||
|
<td valign="top">The type of the function or function object itself (i.e., <tt>T</tt>).
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><tt><nobr>param_type</nobr></tt>
|
||||||
|
</td>
|
||||||
|
<td valign="top">The type that should be used to pass the function or function object as a parameter.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><tt><nobr>result_type</nobr></tt>
|
||||||
|
</td>
|
||||||
|
<td valign="top">The type returned by the function or function object.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><tt><nobr>first_argument_type</nobr></tt>
|
||||||
|
</td>
|
||||||
|
<td valign="top">The type of the first argument to the function or function object.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><tt><nobr>second_argument_type</nobr></tt>
|
||||||
|
</td>
|
||||||
|
<td valign="top">The type of the second argument to the function or function object.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h3>Usage</h3>
|
||||||
|
|
||||||
|
<p><tt><nobr>unary_traits</nobr></tt> should be instantiated with
|
||||||
|
either a function taking a single parameter, or an adaptable unary
|
||||||
|
function object (i.e., a class derived from
|
||||||
|
<tt><nobr>std::unary_function</nobr></tt> or one which provides the
|
||||||
|
same typedefs). (See §20.3.1 in the C++ Standard.)
|
||||||
|
|
||||||
|
<p><tt><nobr>binary_traits</nobr></tt> should be instantiated with
|
||||||
|
either a function taking two parameters, or an adaptable binary
|
||||||
|
function object (i.e., a class derived from
|
||||||
|
<tt><nobr>std::binary_function</nobr></tt> or one which provides the
|
||||||
|
same typedefs). (See §20.3.1 in the C++ Standard.)
|
||||||
|
|
||||||
|
<p>The most common usage of these templates is in function object
|
||||||
|
adapters, thus allowing them to adapt plain functions as well as
|
||||||
|
function objects. You can do this by wherever you would normally
|
||||||
|
write, for example,
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
typename Operation::argument_type
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<p>simply writing
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
typename boost::unary_traits<Operation>::argument_type
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<p>instead.
|
||||||
|
|
||||||
|
<h3>Additional Types Defined</h3>
|
||||||
|
|
||||||
|
<p>In addition to the standard result and argument typedefs, these
|
||||||
|
traits templates define two additional types.
|
||||||
|
|
||||||
|
<h4><tt>function_type</tt></h4>
|
||||||
|
|
||||||
|
<p>This is the type of the function or function object, and can be
|
||||||
|
used in declarations such as</p>
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
template <class Predicate>
|
||||||
|
class unary_negate : // ...
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
private:
|
||||||
|
<strong>typename unary_traits<Predicate>::function_type</strong> pred;
|
||||||
|
};
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<p>If this typedef were not provided, it would not be possible to
|
||||||
|
declare <tt>pred</tt> in a way that would allow
|
||||||
|
<tt><nobr>unary_negate</nobr></tt> to be instantiated with a function
|
||||||
|
type (see the C++ Standard §14.3.1 ¶3).
|
||||||
|
|
||||||
|
<h4><tt>param_type</tt></h4>
|
||||||
|
|
||||||
|
<p>This is a type suitable for passing the function or function object
|
||||||
|
as a parameter to another function. For example,
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
template <class Predicate>
|
||||||
|
class unary_negate : // ...
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit unary_negate(<strong>typename unary_traits<Predicate>::param_type</strong> x)
|
||||||
|
:
|
||||||
|
pred(x)
|
||||||
|
{}
|
||||||
|
// ...
|
||||||
|
};
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<p>Function objects are passed by reference to const; function
|
||||||
|
pointers are passed by value.</p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Limitations</h3>
|
||||||
|
|
||||||
|
<p>This library uses these traits within all function object adapters,
|
||||||
|
theoretically rendering <tt><nobr>ptr_fun</nobr></tt> obsolete.
|
||||||
|
However, third party adapters probably won't take advantage of this
|
||||||
|
mechanism, and so <tt><nobr>ptr_fun</nobr></tt> may still be required.
|
||||||
|
Accordingly, this library also provides <a
|
||||||
|
href="ptr_fun.html">improved versions of the standard function pointer
|
||||||
|
adapters</a>.</p>
|
||||||
|
|
||||||
|
<p>These traits templates will also not work with compilers that fail
|
||||||
|
to support partial specialisation of templates. With these compilers,
|
||||||
|
the traits templates can only be instantiated with adaptable function
|
||||||
|
objects, thus requiring <tt><nobr>ptr_fun</nobr></tt> to be used, even
|
||||||
|
with the function object adapters in this library.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<p>Copyright © 2000 Cadenza New Zealand Ltd. Permission to copy,
|
||||||
|
use, modify, sell and distribute this document is granted provided
|
||||||
|
this copyright notice appears in all copies. This document is provided
|
||||||
|
"as is" without express or implied warranty, and with no claim as to
|
||||||
|
its suitability for any purpose.</p>
|
||||||
|
|
||||||
|
<p>Revised 28 June 2000</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
542
include/boost/functional.hpp
Normal file
542
include/boost/functional.hpp
Normal file
@@ -0,0 +1,542 @@
|
|||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
// Boost functional.hpp header file
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2000
|
||||||
|
// Cadenza New Zealand Ltd
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, distribute and sell this software
|
||||||
|
// and its documentation for any purpose is hereby granted without
|
||||||
|
// fee, provided that the above copyright notice appears in all copies
|
||||||
|
// and that both the copyright notice and this permission notice
|
||||||
|
// appear in supporting documentation. Cadenza New Zealand Ltd makes
|
||||||
|
// no representations about the suitability of this software for any
|
||||||
|
// purpose. It is provided "as is" without express or implied
|
||||||
|
// warranty.
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
// $Id$
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
// $Log$
|
||||||
|
// Revision 1.2 2000/08/01 07:53:58 mark_rodgers
|
||||||
|
// Workarounds for Metrowerks as suggested by Fabrice Truillot.
|
||||||
|
//
|
||||||
|
// Revision 1.1.1.1 2000/07/07 16:03:47 beman
|
||||||
|
// 1.16.1 initial CVS checkin
|
||||||
|
//
|
||||||
|
// Revision 1.3 2000/06/26 09:44:54 mark
|
||||||
|
// Updated following feedback from Jens Maurer.
|
||||||
|
//
|
||||||
|
// Revision 1.2 2000/05/17 08:36:30 mark
|
||||||
|
// Fixed problems with function object traits thanks to ideas
|
||||||
|
// from John Maddock.
|
||||||
|
//
|
||||||
|
// Revision 1.1 2000/05/07 08:26:51 mark
|
||||||
|
// Initial revision
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef BOOST_FUNCTIONAL_HPP
|
||||||
|
#define BOOST_FUNCTIONAL_HPP
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <boost/call_traits.hpp>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// The following traits classes allow us to avoid the need for ptr_fun
|
||||||
|
// because the types of arguments and the result of a function can be
|
||||||
|
// deduced.
|
||||||
|
//
|
||||||
|
// In addition to the standard types defined in unary_function and
|
||||||
|
// binary_function, we add
|
||||||
|
//
|
||||||
|
// - function_type, the type of the function or function object itself.
|
||||||
|
//
|
||||||
|
// - param_type, the type that should be used for passing the function or
|
||||||
|
// function object as an argument.
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template <class Operation>
|
||||||
|
struct unary_traits_imp;
|
||||||
|
|
||||||
|
template <class Operation>
|
||||||
|
struct unary_traits_imp<Operation*>
|
||||||
|
{
|
||||||
|
typedef Operation function_type;
|
||||||
|
typedef const function_type & param_type;
|
||||||
|
typedef typename Operation::result_type result_type;
|
||||||
|
typedef typename Operation::argument_type argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class R, class A>
|
||||||
|
struct unary_traits_imp<R(*)(A)>
|
||||||
|
{
|
||||||
|
typedef R (*function_type)(A);
|
||||||
|
typedef R (*param_type)(A);
|
||||||
|
typedef R result_type;
|
||||||
|
typedef A argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Operation>
|
||||||
|
struct binary_traits_imp;
|
||||||
|
|
||||||
|
template <class Operation>
|
||||||
|
struct binary_traits_imp<Operation*>
|
||||||
|
{
|
||||||
|
typedef Operation function_type;
|
||||||
|
typedef const function_type & param_type;
|
||||||
|
typedef typename Operation::result_type result_type;
|
||||||
|
typedef typename Operation::first_argument_type first_argument_type;
|
||||||
|
typedef typename Operation::second_argument_type second_argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class R, class A1, class A2>
|
||||||
|
struct binary_traits_imp<R(*)(A1,A2)>
|
||||||
|
{
|
||||||
|
typedef R (*function_type)(A1,A2);
|
||||||
|
typedef R (*param_type)(A1,A2);
|
||||||
|
typedef R result_type;
|
||||||
|
typedef A1 first_argument_type;
|
||||||
|
typedef A2 second_argument_type;
|
||||||
|
};
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <class Operation>
|
||||||
|
struct unary_traits
|
||||||
|
{
|
||||||
|
typedef typename detail::unary_traits_imp<Operation*>::function_type function_type;
|
||||||
|
typedef typename detail::unary_traits_imp<Operation*>::param_type param_type;
|
||||||
|
typedef typename detail::unary_traits_imp<Operation*>::result_type result_type;
|
||||||
|
typedef typename detail::unary_traits_imp<Operation*>::argument_type argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class R, class A>
|
||||||
|
struct unary_traits<R(*)(A)>
|
||||||
|
{
|
||||||
|
typedef R (*function_type)(A);
|
||||||
|
typedef R (*param_type)(A);
|
||||||
|
typedef R result_type;
|
||||||
|
typedef A argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Operation>
|
||||||
|
struct binary_traits
|
||||||
|
{
|
||||||
|
typedef typename detail::binary_traits_imp<Operation*>::function_type function_type;
|
||||||
|
typedef typename detail::binary_traits_imp<Operation*>::param_type param_type;
|
||||||
|
typedef typename detail::binary_traits_imp<Operation*>::result_type result_type;
|
||||||
|
typedef typename detail::binary_traits_imp<Operation*>::first_argument_type first_argument_type;
|
||||||
|
typedef typename detail::binary_traits_imp<Operation*>::second_argument_type second_argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class R, class A1, class A2>
|
||||||
|
struct binary_traits<R(*)(A1,A2)>
|
||||||
|
{
|
||||||
|
typedef R (*function_type)(A1,A2);
|
||||||
|
typedef R (*param_type)(A1,A2);
|
||||||
|
typedef R result_type;
|
||||||
|
typedef A1 first_argument_type;
|
||||||
|
typedef A2 second_argument_type;
|
||||||
|
};
|
||||||
|
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// If we have no partial specialisation available, decay to a situation
|
||||||
|
// that is no worse than in the Standard, i.e., ptr_fun will be required.
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template <class Operation>
|
||||||
|
struct unary_traits
|
||||||
|
{
|
||||||
|
typedef Operation function_type;
|
||||||
|
typedef const Operation& param_type;
|
||||||
|
typedef typename Operation::result_type result_type;
|
||||||
|
typedef typename Operation::argument_type argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Operation>
|
||||||
|
struct binary_traits
|
||||||
|
{
|
||||||
|
typedef Operation function_type;
|
||||||
|
typedef const Operation & param_type;
|
||||||
|
typedef typename Operation::result_type result_type;
|
||||||
|
typedef typename Operation::first_argument_type first_argument_type;
|
||||||
|
typedef typename Operation::second_argument_type second_argument_type;
|
||||||
|
};
|
||||||
|
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// unary_negate, not1
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
template <class Predicate>
|
||||||
|
class unary_negate
|
||||||
|
: public std::unary_function<typename unary_traits<Predicate>::argument_type,bool>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit unary_negate(typename unary_traits<Predicate>::param_type x)
|
||||||
|
:
|
||||||
|
pred(x)
|
||||||
|
{}
|
||||||
|
bool operator()(typename call_traits<typename unary_traits<Predicate>::argument_type>::param_type x) const
|
||||||
|
{
|
||||||
|
return !pred(x);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
typename unary_traits<Predicate>::function_type pred;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Predicate>
|
||||||
|
unary_negate<Predicate> not1(const Predicate &pred)
|
||||||
|
{
|
||||||
|
// The cast is to placate Borland C++Builder in certain circumstances.
|
||||||
|
// I don't think it should be necessary.
|
||||||
|
return unary_negate<Predicate>((typename unary_traits<Predicate>::param_type)pred);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// binary_negate, not2
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
template <class Predicate>
|
||||||
|
class binary_negate
|
||||||
|
: public std::binary_function<typename binary_traits<Predicate>::first_argument_type,
|
||||||
|
typename binary_traits<Predicate>::second_argument_type,
|
||||||
|
bool>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit binary_negate(typename binary_traits<Predicate>::param_type x)
|
||||||
|
:
|
||||||
|
pred(x)
|
||||||
|
{}
|
||||||
|
bool operator()(typename call_traits<typename binary_traits<Predicate>::first_argument_type>::param_type x,
|
||||||
|
typename call_traits<typename binary_traits<Predicate>::second_argument_type>::param_type y) const
|
||||||
|
{
|
||||||
|
return !pred(x,y);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
typename binary_traits<Predicate>::function_type pred;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Predicate>
|
||||||
|
binary_negate<Predicate> not2(const Predicate &pred)
|
||||||
|
{
|
||||||
|
// The cast is to placate Borland C++Builder in certain circumstances.
|
||||||
|
// I don't think it should be necessary.
|
||||||
|
return binary_negate<Predicate>((typename binary_traits<Predicate>::param_type)pred);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// binder1st, bind1st
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
template <class Operation>
|
||||||
|
class binder1st
|
||||||
|
: public std::unary_function<typename binary_traits<Operation>::second_argument_type,
|
||||||
|
typename binary_traits<Operation>::result_type>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
binder1st(typename binary_traits<Operation>::param_type x,
|
||||||
|
typename call_traits<typename binary_traits<Operation>::first_argument_type>::param_type y)
|
||||||
|
:
|
||||||
|
op(x), value(y)
|
||||||
|
{}
|
||||||
|
|
||||||
|
typename binary_traits<Operation>::result_type
|
||||||
|
operator()(typename call_traits<typename binary_traits<Operation>::second_argument_type>::param_type x) const
|
||||||
|
{
|
||||||
|
return op(value, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
typename binary_traits<Operation>::function_type op;
|
||||||
|
typename binary_traits<Operation>::first_argument_type value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Operation>
|
||||||
|
inline binder1st<Operation> bind1st(const Operation &op,
|
||||||
|
typename call_traits<
|
||||||
|
typename binary_traits<Operation>::first_argument_type
|
||||||
|
>::param_type x)
|
||||||
|
{
|
||||||
|
// The cast is to placate Borland C++Builder in certain circumstances.
|
||||||
|
// I don't think it should be necessary.
|
||||||
|
return binder1st<Operation>((typename binary_traits<Operation>::param_type)op, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// binder2nd, bind2nd
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
template <class Operation>
|
||||||
|
class binder2nd
|
||||||
|
: public std::unary_function<typename binary_traits<Operation>::first_argument_type,
|
||||||
|
typename binary_traits<Operation>::result_type>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
binder2nd(typename binary_traits<Operation>::param_type x,
|
||||||
|
typename call_traits<typename binary_traits<Operation>::second_argument_type>::param_type y)
|
||||||
|
:
|
||||||
|
op(x), value(y)
|
||||||
|
{}
|
||||||
|
|
||||||
|
typename binary_traits<Operation>::result_type
|
||||||
|
operator()(typename call_traits<typename binary_traits<Operation>::first_argument_type>::param_type x) const
|
||||||
|
{
|
||||||
|
return op(x, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
typename binary_traits<Operation>::function_type op;
|
||||||
|
typename binary_traits<Operation>::second_argument_type value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Operation>
|
||||||
|
inline binder2nd<Operation> bind2nd(const Operation &op,
|
||||||
|
typename call_traits<
|
||||||
|
typename binary_traits<Operation>::second_argument_type
|
||||||
|
>::param_type x)
|
||||||
|
{
|
||||||
|
// The cast is to placate Borland C++Builder in certain circumstances.
|
||||||
|
// I don't think it should be necessary.
|
||||||
|
return binder2nd<Operation>((typename binary_traits<Operation>::param_type)op, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// mem_fun, etc
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
template <class S, class T>
|
||||||
|
class mem_fun_t : public std::unary_function<T*, S>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit mem_fun_t(S (T::*p)())
|
||||||
|
:
|
||||||
|
ptr(p)
|
||||||
|
{}
|
||||||
|
S operator()(T* p) const
|
||||||
|
{
|
||||||
|
return (p->*ptr)();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
S (T::*ptr)();
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class S, class T, class A>
|
||||||
|
class mem_fun1_t : public std::binary_function<T*, A, S>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit mem_fun1_t(S (T::*p)(A))
|
||||||
|
:
|
||||||
|
ptr(p)
|
||||||
|
{}
|
||||||
|
S operator()(T* p, typename call_traits<A>::param_type x) const
|
||||||
|
{
|
||||||
|
return (p->*ptr)(x);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
S (T::*ptr)(A);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class S, class T>
|
||||||
|
class const_mem_fun_t : public std::unary_function<const T*, S>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit const_mem_fun_t(S (T::*p)() const)
|
||||||
|
:
|
||||||
|
ptr(p)
|
||||||
|
{}
|
||||||
|
S operator()(const T* p) const
|
||||||
|
{
|
||||||
|
return (p->*ptr)();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
S (T::*ptr)() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class S, class T, class A>
|
||||||
|
class const_mem_fun1_t : public std::binary_function<const T*, A, S>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit const_mem_fun1_t(S (T::*p)(A) const)
|
||||||
|
:
|
||||||
|
ptr(p)
|
||||||
|
{}
|
||||||
|
S operator()(const T* p, typename call_traits<A>::param_type x) const
|
||||||
|
{
|
||||||
|
return (p->*ptr)(x);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
S (T::*ptr)(A) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class S, class T>
|
||||||
|
inline mem_fun_t<S,T> mem_fun(S (T::*f)())
|
||||||
|
{
|
||||||
|
return mem_fun_t<S,T>(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class S, class T, class A>
|
||||||
|
inline mem_fun1_t<S,T,A> mem_fun(S (T::*f)(A))
|
||||||
|
{
|
||||||
|
return mem_fun1_t<S,T,A>(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_POINTER_TO_MEMBER_CONST
|
||||||
|
template<class S, class T>
|
||||||
|
inline const_mem_fun_t<S,T> mem_fun(S (T::*f)() const)
|
||||||
|
{
|
||||||
|
return const_mem_fun_t<S,T>(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class S, class T, class A>
|
||||||
|
inline const_mem_fun1_t<S,T,A> mem_fun(S (T::*f)(A) const)
|
||||||
|
{
|
||||||
|
return const_mem_fun1_t<S,T,A>(f);
|
||||||
|
}
|
||||||
|
#endif // BOOST_NO_POINTER_TO_MEMBER_CONST
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// mem_fun_ref, etc
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
template <class S, class T>
|
||||||
|
class mem_fun_ref_t : public std::unary_function<T&, S>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit mem_fun_ref_t(S (T::*p)())
|
||||||
|
:
|
||||||
|
ptr(p)
|
||||||
|
{}
|
||||||
|
S operator()(T& p) const
|
||||||
|
{
|
||||||
|
return (p.*ptr)();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
S (T::*ptr)();
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class S, class T, class A>
|
||||||
|
class mem_fun1_ref_t : public std::binary_function<T&, A, S>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit mem_fun1_ref_t(S (T::*p)(A))
|
||||||
|
:
|
||||||
|
ptr(p)
|
||||||
|
{}
|
||||||
|
S operator()(T& p, typename call_traits<A>::param_type x) const
|
||||||
|
{
|
||||||
|
return (p.*ptr)(x);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
S (T::*ptr)(A);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class S, class T>
|
||||||
|
class const_mem_fun_ref_t : public std::unary_function<const T&, S>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit const_mem_fun_ref_t(S (T::*p)() const)
|
||||||
|
:
|
||||||
|
ptr(p)
|
||||||
|
{}
|
||||||
|
|
||||||
|
S operator()(const T &p) const
|
||||||
|
{
|
||||||
|
return (p.*ptr)();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
S (T::*ptr)() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class S, class T, class A>
|
||||||
|
class const_mem_fun1_ref_t : public std::binary_function<const T&, A, S>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit const_mem_fun1_ref_t(S (T::*p)(A) const)
|
||||||
|
:
|
||||||
|
ptr(p)
|
||||||
|
{}
|
||||||
|
|
||||||
|
S operator()(const T& p, typename call_traits<A>::param_type x) const
|
||||||
|
{
|
||||||
|
return (p.*ptr)(x);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
S (T::*ptr)(A) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class S, class T>
|
||||||
|
inline mem_fun_ref_t<S,T> mem_fun_ref(S (T::*f)())
|
||||||
|
{
|
||||||
|
return mem_fun_ref_t<S,T>(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class S, class T, class A>
|
||||||
|
inline mem_fun1_ref_t<S,T,A> mem_fun_ref(S (T::*f)(A))
|
||||||
|
{
|
||||||
|
return mem_fun1_ref_t<S,T,A>(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_POINTER_TO_MEMBER_CONST
|
||||||
|
template<class S, class T>
|
||||||
|
inline const_mem_fun_ref_t<S,T> mem_fun_ref(S (T::*f)() const)
|
||||||
|
{
|
||||||
|
return const_mem_fun_ref_t<S,T>(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class S, class T, class A>
|
||||||
|
inline const_mem_fun1_ref_t<S,T,A> mem_fun_ref(S (T::*f)(A) const)
|
||||||
|
{
|
||||||
|
return const_mem_fun1_ref_t<S,T,A>(f);
|
||||||
|
}
|
||||||
|
#endif // BOOST_NO_POINTER_TO_MEMBER_CONST
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// ptr_fun
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
template <class Arg, class Result>
|
||||||
|
class pointer_to_unary_function : public std::unary_function<Arg,Result>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit pointer_to_unary_function(Result (*f)(Arg))
|
||||||
|
:
|
||||||
|
func(f)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Result operator()(typename call_traits<Arg>::param_type x) const
|
||||||
|
{
|
||||||
|
return func(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result (*func)(Arg);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Arg, class Result>
|
||||||
|
inline pointer_to_unary_function<Arg,Result> ptr_fun(Result (*f)(Arg))
|
||||||
|
{
|
||||||
|
return pointer_to_unary_function<Arg,Result>(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Arg1, class Arg2, class Result>
|
||||||
|
class pointer_to_binary_function : public std::binary_function<Arg1,Arg2,Result>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit pointer_to_binary_function(Result (*f)(Arg1, Arg2))
|
||||||
|
:
|
||||||
|
func(f)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Result operator()(typename call_traits<Arg1>::param_type x, typename call_traits<Arg2>::param_type y) const
|
||||||
|
{
|
||||||
|
return func(x,y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result (*func)(Arg1, Arg2);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Arg1, class Arg2, class Result>
|
||||||
|
inline pointer_to_binary_function<Arg1,Arg2,Result> ptr_fun(Result (*f)(Arg1, Arg2))
|
||||||
|
{
|
||||||
|
return pointer_to_binary_function<Arg1,Arg2,Result>(f);
|
||||||
|
}
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif
|
184
index.html
Normal file
184
index.html
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||||
|
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||||
|
<title>Boost Function Object Adapter Library</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body bgcolor="#FFFFFF" text="#000000">
|
||||||
|
|
||||||
|
<table border="1" bgcolor="#007F7F" cellpadding="2">
|
||||||
|
<tr>
|
||||||
|
<td bgcolor="#FFFFFF"><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" width="277" height="86"></td>
|
||||||
|
<td><a href="../../index.htm"><font face="Arial" color="#FFFFFF"><big>Home</big></font></a></td>
|
||||||
|
<td><a href="../../libraries.htm"><font face="Arial" color="#FFFFFF"><big>Libraries</big></font></a></td>
|
||||||
|
<td><a href="../../people.htm"><font face="Arial" color="#FFFFFF"><big>People</big></font></a></td>
|
||||||
|
<td><a href="../../more/faq.htm"><font face="Arial" color="#FFFFFF"><big>FAQ</big></font></a></td>
|
||||||
|
<td><a href="../../more/index.htm"><font face="Arial" color="#FFFFFF"><big>More</big></font></a></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<h1>Improved Function Object Adapters</h1>
|
||||||
|
<p>The header <nobr><a href="../../boost/functional.hpp">functional.hpp</a></nobr>
|
||||||
|
provides enhancements to the function object adapters specified in the C++
|
||||||
|
Standard Library (sections 20.3.5, through to 20.3.8). The enhancements are
|
||||||
|
principally possible due to two changes:</p>
|
||||||
|
<ol>
|
||||||
|
<li>We use the Boost <nobr><tt><a href="../utility/call_traits.htm">call_traits</a></tt></nobr>
|
||||||
|
templates to avoid the problem of <a href="binders.html#refref">references
|
||||||
|
to references</a>, and to improve the efficiency of <a href="mem_fun.html#args">parameter
|
||||||
|
passing</a>.</li>
|
||||||
|
<li>We use two <a href="function_traits.html">function object traits</a> class
|
||||||
|
templates to avoid the need for <nobr><tt><a href="ptr_fun.html">ptr_fun</a></tt></nobr>
|
||||||
|
with the adapters in this library.</li>
|
||||||
|
</ol>
|
||||||
|
<h3>Contents</h3>
|
||||||
|
<p>The header contains the following function and class templates:</p>
|
||||||
|
<table border="1" cellpadding="5">
|
||||||
|
<tr>
|
||||||
|
<th align="left"><a href="function_traits.html">Function object traits</a>
|
||||||
|
<td valign="top"><tt><nobr>unary_traits</nobr><br>
|
||||||
|
<nobr>binary_traits</nobr></tt></td>
|
||||||
|
<td valign="top">Used to determine the types of function objects' and
|
||||||
|
functions' arguments. Eliminate the necessity for <nobr><tt>ptr_fun</tt></nobr>.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th align="left"><a href="negators.html">Negators</a></th>
|
||||||
|
<td valign="top"><tt><nobr>unary_negate</nobr><br>
|
||||||
|
<nobr>binary_negate</nobr><br>
|
||||||
|
<nobr>not1</nobr><br>
|
||||||
|
<nobr>not2</nobr></tt></td>
|
||||||
|
<td valign="top">Based on section 20.3.5 of the standard.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th align="left"><a href="binders.html">Binders</a></th>
|
||||||
|
<td valign="top"><tt><nobr>binder1st</nobr><br>
|
||||||
|
<nobr>binder2nd</nobr><br>
|
||||||
|
<nobr>bind1st</nobr><br>
|
||||||
|
<nobr>bind2nd</nobr></tt></td>
|
||||||
|
<td valign="top">Based on section 20.3.6 of the standard.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th align="left"><a href="ptr_fun.html">Adapters for pointers to functions</a></th>
|
||||||
|
<td valign="top"><tt><nobr>pointer_to_unary_function</nobr><br>
|
||||||
|
<nobr>pointer_to_binary_function</nobr><br>
|
||||||
|
<nobr>ptr_fun</nobr></tt></td>
|
||||||
|
<td valign="top">Based on section 20.3.7 of the standard. Not required for
|
||||||
|
use with this library since the binders and negators can adapt functions,
|
||||||
|
but may be needed with third party adapters.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th align="left"><a href="mem_fun.html">Adapters for pointers to member
|
||||||
|
functions</a></th>
|
||||||
|
<td valign="top"><tt><nobr>mem_fun_t</nobr><br>
|
||||||
|
<nobr>mem_fun1_t</nobr><br>
|
||||||
|
<nobr>const_mem_fun_t</nobr><br>
|
||||||
|
<nobr>const_mem_fun1_t</nobr><br>
|
||||||
|
<nobr>mem_fun_ref_t</nobr><br>
|
||||||
|
<nobr>mem_fun1_ref_t</nobr><br>
|
||||||
|
<nobr>const_mem_fun_ref_t</nobr><br>
|
||||||
|
<nobr>const_mem_fun1_ref_t</nobr><br>
|
||||||
|
<nobr>mem_fun</nobr><br>
|
||||||
|
<nobr>mem_fun_ref</nobr></tt></td>
|
||||||
|
<td valign="top">Based on section 20.3.8 of the standard.</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<h3>Usage</h3>
|
||||||
|
<p>Using these adapters should be pretty much the same as using the standard
|
||||||
|
function object adapters; the only differences are that you need to write <nobr><tt>boost::</tt></nobr>
|
||||||
|
instead of <nobr><tt>std::</tt></nobr>, and that you will get fewer headaches.</p>
|
||||||
|
<p>For example, suppose you had a <tt>Person</tt> class that contained a <nobr><tt>set_name</tt></nobr>
|
||||||
|
function:
|
||||||
|
<blockquote>
|
||||||
|
<pre>
|
||||||
|
class Person
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void set_name(const std::string &name);
|
||||||
|
// ...
|
||||||
|
};
|
||||||
|
</pre>
|
||||||
|
</blockquote>
|
||||||
|
<p>You could rename a bunch of people in a collection, <tt>c</tt>, by writing</p>
|
||||||
|
<blockquote>
|
||||||
|
<pre>
|
||||||
|
std::for_each(c.begin(), c.end(),
|
||||||
|
boost::bind2nd(boost::mem_fun_ref(&Person::set_name), "Fred"));
|
||||||
|
</pre>
|
||||||
|
</blockquote>
|
||||||
|
<p>If the standard adapters had been used instead then this code would normally
|
||||||
|
fail to compile, because <tt><nobr>set_name</nobr></tt> takes a reference
|
||||||
|
argument. Refer to the comments in the <a href="binders.html#refref">binder
|
||||||
|
documentation</a> to explain why this is so.</p>
|
||||||
|
<h3>Compiler Compatibility</h3>
|
||||||
|
<p>The header and <a href="function_test.cpp">test program</a> have been
|
||||||
|
compiled with the following compilers:</p>
|
||||||
|
<table border="1" cellpadding="5">
|
||||||
|
<tr>
|
||||||
|
<th>Compiler</th>
|
||||||
|
<th>Comments</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top">Borland C++Builder 4 Update 2</td>
|
||||||
|
<td valign="top">No known issues.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top">Borland C++ 5.5</td>
|
||||||
|
<td valign="top">No known issues.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top">g++ 2.95.2</td>
|
||||||
|
<td valign="top">No known issues.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top">Microsoft Visual C++ Service Pack 3</td>
|
||||||
|
<td valign="top">Compiler lacks partial specialisation, so this library
|
||||||
|
offers little more than is provided by the standard adapters:
|
||||||
|
<ul>
|
||||||
|
<li>The <nobr><tt>call_traits</tt></nobr> mechanism is unable to prevent
|
||||||
|
references to references, and so the adapters in this library will be
|
||||||
|
usable in fewer situations.</li>
|
||||||
|
<li>The <nobr><tt>function_traits</tt></nobr> mechanism is unable to
|
||||||
|
determine the argument and result types of functions, therefore <nobr><tt>ptr_fun</tt></nobr>
|
||||||
|
continues to be required to adapt functions.
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<h3>Future Directions</h3>
|
||||||
|
<p>This library's primary focus is to solve the problem of references to
|
||||||
|
references while maintaining as much compatibility as possible with the standard
|
||||||
|
library. This allows you to use the techniques you read about in books and
|
||||||
|
magazines with many of today's compilers.</p>
|
||||||
|
<p>In the longer term, even better solutions are likely:</p>
|
||||||
|
<ol>
|
||||||
|
<li>Several Boost members are working on expression template libraries. These
|
||||||
|
will allow a more natural syntax for combining and adapting functions. As
|
||||||
|
this is a new technology, it may be some time before it has matured and is
|
||||||
|
widely supported by major compilers but shows great promise. In the
|
||||||
|
meantime, the functional.hpp library fills the gap.</li>
|
||||||
|
<li>The Standard Committee has recognised the problem of references to
|
||||||
|
references occurring during template instantiation and has moved to fix the
|
||||||
|
standard (see the <a href="http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#106">C++
|
||||||
|
standard core language active issues list</a>).</li>
|
||||||
|
</ol>
|
||||||
|
<h3>Author</h3>
|
||||||
|
<p><a href="../../people/mark_rodgers.htm">Mark Rodgers</a></p>
|
||||||
|
<h3>Acknowledgements</h3>
|
||||||
|
<p>Thanks to <a href="../../people/john_maddock.htm">John Maddock</a> for
|
||||||
|
suggesting the mechanism that allowed the function objects traits to work
|
||||||
|
correctly. <a href="../../people/jens_maurer.htm">Jens Maurer</a> provided
|
||||||
|
invaluable feedback during the <a href="../../more/formal_review_process.htm">formal
|
||||||
|
review process</a>.
|
||||||
|
<hr>
|
||||||
|
<p>Copyright <20> 2000 Cadenza New Zealand Ltd. Permission to copy, use, modify,
|
||||||
|
sell and distribute this document is granted provided this copyright notice
|
||||||
|
appears in all copies. This document is provided "as is" without
|
||||||
|
express or implied warranty, and with no claim as to its suitability for any
|
||||||
|
purpose.</p>
|
||||||
|
<p>Revised 28 June 2000</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
171
mem_fun.html
Normal file
171
mem_fun.html
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<title>Boost Function Object Adapter Library</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body bgcolor="#FFFFFF" text="#000000">
|
||||||
|
|
||||||
|
<table border="1" bgcolor="#007F7F" cellpadding="2">
|
||||||
|
<tr>
|
||||||
|
<td bgcolor="#FFFFFF"><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" WIDTH="277" HEIGHT="86"></td>
|
||||||
|
<td><a href="../../index.htm"><font face="Arial" color="#FFFFFF"><big>Home </big></font></a></td>
|
||||||
|
<td><a href="../../libraries.htm"><font face="Arial" color="#FFFFFF"><big>Libraries </big></font></a></td>
|
||||||
|
<td><a href="../../people.htm"><font face="Arial" color="#FFFFFF"><big>People </big></font></a></td>
|
||||||
|
<td><a href="../../more/faq.htm"><font face="Arial" color="#FFFFFF"><big>FAQ </big></font></a></td>
|
||||||
|
<td><a href="../../more/index.htm"><font face="Arial" color="#FFFFFF"><big>More </big></font></a></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h1>Member Function Adapters</h1>
|
||||||
|
|
||||||
|
<p>The header <nobr><a
|
||||||
|
href="../../boost/functional.hpp">functional.hpp</a></nobr> includes
|
||||||
|
improved versions of the full range of member function adapters from
|
||||||
|
the the C++ Standard Library <nobr>(§ 20.3.8):</nobr></p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><tt>mem_fun_t</tt></li>
|
||||||
|
<li><tt>mem_fun1_t</tt></li>
|
||||||
|
<li><tt>const_mem_fun_t</tt></li>
|
||||||
|
<li><tt>const_mem_fun1_t</tt></li>
|
||||||
|
<li><tt>mem_fun_ref_t</tt></li>
|
||||||
|
<li><tt>mem_fun1_ref_t</tt></li>
|
||||||
|
<li><tt>const_mem_fun_ref_t</tt></li>
|
||||||
|
<li><tt>const_mem_fun1_ref_t</tt></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>as well as the corresponding overloaded helper functions<p>
|
||||||
|
<ul>
|
||||||
|
<li><tt>mem_fun</tt></li>
|
||||||
|
<li><tt>mem_fun_ref</tt></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>The following changes have been made to the adapters as specified
|
||||||
|
in the Standard:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>The <tt><nobr>first_argument_type</nobr></tt> typedef has been
|
||||||
|
corrected for the <nobr><tt>const_</tt></nobr> family of member
|
||||||
|
function adapters (see <a href="#firstarg">below</a>).</li>
|
||||||
|
|
||||||
|
<li>The argument passed to <tt><nobr>mem_fun1_t</nobr></tt> and its
|
||||||
|
variants is passed using the
|
||||||
|
<tt><nobr>call_traits::param_type</nobr></tt> for the member
|
||||||
|
function's argument type.
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3 id="firstarg">first_argument_type</h3>
|
||||||
|
|
||||||
|
<p>The standard specifies <tt><nobr>const_mem_fun1_t</nobr></tt>, for example, like this:
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
template <class S, class T, class A> class const_mem_fun1_t
|
||||||
|
: public binary_function<<strong>T*</strong>, A, S> {
|
||||||
|
public:
|
||||||
|
explicit const_mem_fun1_t(S (T::*p)(A) const);
|
||||||
|
S operator()(<strong>const T*</strong> p, A x) const;
|
||||||
|
};
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<p>Note that the first argument to
|
||||||
|
<tt><nobr>binary_function</nobr></tt> is <tt><nobr>T*</nobr></tt>
|
||||||
|
despite the fact that the first argument to <tt><nobr>operator()</nobr></tt> is
|
||||||
|
actually of type <tt><nobr><em>const</em> T*</nobr></tt>.
|
||||||
|
|
||||||
|
<p>Does this matter? Well, consider what happens when we write
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
struct Foo { void bar(int) const; };
|
||||||
|
const Foo *cp = new Foo;
|
||||||
|
std::bind1st(std::mem_fun(&Foo::bar), cp);
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<p>We have created a <tt><nobr>const_mem_fun1_t</nobr></tt> object
|
||||||
|
which will effectively contain the following
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
typedef Foo* first_argument_type;
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<p>The <tt><nobr>bind1st</nobr></tt> will then create a
|
||||||
|
<tt><nobr>binder1st</nobr></tt> object that will use this
|
||||||
|
<tt><nobr>typedef</nobr></tt> as the type of a member which will be
|
||||||
|
initialised with <tt><nobr>cp</nobr></tt>. In other words, we will
|
||||||
|
need to initialise a <tt><nobr>Foo*</nobr></tt> member with a
|
||||||
|
<tt><nobr>const Foo*</nobr></tt> pointer! Clearly this is not
|
||||||
|
possible, so to implement this your Standard Library vendor will have
|
||||||
|
had to cast away the constness of <tt><nobr>cp</nobr></tt>, probably
|
||||||
|
within the body of <tt><nobr>bind1st</nobr></tt>.
|
||||||
|
|
||||||
|
<p>This hack will not suffice with the improved <a
|
||||||
|
href="binders.html">binders</a> in this library, so we have had to
|
||||||
|
provide corrected versions of the member function adapters as well.
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="args">Argument Types</h3>
|
||||||
|
|
||||||
|
<p>The standard defines <nobr><tt>mem_fun1_t</tt></nobr>, for example, like this
|
||||||
|
<nobr>(§20.3.8 ¶2):</nobr>
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
template <class S, class T, class A> class mem_fun1_t
|
||||||
|
: public binary_function<T*, A, S> {
|
||||||
|
public:
|
||||||
|
explicit mem_fun1_t(S (T::*p)(<strong>A</strong>));
|
||||||
|
S operator()(T* p, <strong>A</strong> x) const;
|
||||||
|
};
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<p>Note that the second argument to <nobr><tt>operator()</tt></nobr> is
|
||||||
|
exactly the same type as the argument to the member function. If this
|
||||||
|
is a value type, the argument will be passed by value and copied twice.
|
||||||
|
|
||||||
|
<p>However, if we were to try and eliminate this inefficiency by
|
||||||
|
instead declaring the argument as <nobr><tt>const A&</tt></nobr>, then
|
||||||
|
if A were a reference type, we would have a reference to a reference,
|
||||||
|
which is currently illegal (but see <a
|
||||||
|
href="http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#106">C++
|
||||||
|
core language issue number 106)</a>
|
||||||
|
|
||||||
|
<p>So the way in which we want to declare the second argument for
|
||||||
|
<nobr><tt>operator()</tt></nobr> depends on whether or not the member
|
||||||
|
function's argument is a reference. If it is a reference, we want to
|
||||||
|
declare it simply as <nobr><tt>A</tt></nobr>; if it is a value we want
|
||||||
|
to declare it as <nobr><tt>const A&</tt></nobr>.
|
||||||
|
|
||||||
|
<p>The Boost <nobr><a
|
||||||
|
href="../utility/call_traits.htm">call_traits</a></nobr> class
|
||||||
|
template contains a <tt><nobr>param_type</nobr></tt> typedef, which
|
||||||
|
uses partial specialisation to make precisely this decision. By
|
||||||
|
declaring the <nobr><tt>operator()</tt></nobr> as
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
S operator()(T* p, typename call_traits<A>::param_type x) const
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<p>we achieve the desired result - we improve efficiency without
|
||||||
|
generating references to references.</p>
|
||||||
|
|
||||||
|
<h3>Limitations</h3>
|
||||||
|
|
||||||
|
<p>The call traits template used to realise some improvements relies
|
||||||
|
on partial specialisation, so these improvements are only available on
|
||||||
|
compilers that support that feature. With other compilers, the
|
||||||
|
argument passed to the member function (in the
|
||||||
|
<nobr><tt>mem_fun1_t</tt></nobr> family) will always be passed by
|
||||||
|
reference, thus generating the possibility of references to references.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<p>Copyright © 2000 Cadenza New Zealand Ltd. Permission to copy,
|
||||||
|
use, modify, sell and distribute this document is granted provided
|
||||||
|
this copyright notice appears in all copies. This document is provided
|
||||||
|
"as is" without express or implied warranty, and with no claim as to
|
||||||
|
its suitability for any purpose.</p>
|
||||||
|
|
||||||
|
<p>Revised 28 June 2000</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
132
negators.html
Normal file
132
negators.html
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<title>Boost Function Object Adapter Library</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body bgcolor="#FFFFFF" text="#000000">
|
||||||
|
|
||||||
|
<table border="1" bgcolor="#007F7F" cellpadding="2">
|
||||||
|
<tr>
|
||||||
|
<td bgcolor="#FFFFFF"><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" WIDTH="277" HEIGHT="86"></td>
|
||||||
|
<td><a href="../../index.htm"><font face="Arial" color="#FFFFFF"><big>Home </big></font></a></td>
|
||||||
|
<td><a href="../../libraries.htm"><font face="Arial" color="#FFFFFF"><big>Libraries </big></font></a></td>
|
||||||
|
<td><a href="../../people.htm"><font face="Arial" color="#FFFFFF"><big>People </big></font></a></td>
|
||||||
|
<td><a href="../../more/faq.htm"><font face="Arial" color="#FFFFFF"><big>FAQ </big></font></a></td>
|
||||||
|
<td><a href="../../more/index.htm"><font face="Arial" color="#FFFFFF"><big>More </big></font></a></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h1>Negators</h1>
|
||||||
|
|
||||||
|
<p>The header <nobr><a
|
||||||
|
href="../../boost/functional.hpp">functional.hpp</a></nobr> provides
|
||||||
|
enhanced versions of both the negator adapters from the C++ Standard
|
||||||
|
Library (§20.3.5):</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><tt>unary_negate</tt></li>
|
||||||
|
<li><tt>binary_negate</tt></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>As well as the corresponding helper functions</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><tt>not1</tt></li>
|
||||||
|
<li><tt>not2</tt></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>However, the negators in this library improve on the standard
|
||||||
|
versions in two ways:
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>They use <a href="function_traits.html">function object traits</a>
|
||||||
|
to avoid the need for <tt><nobr>ptr_fun</nobr></tt> when negating a
|
||||||
|
function rather than an adaptable function object.
|
||||||
|
</li>
|
||||||
|
<li>They use Boost <nobr><a
|
||||||
|
href="../utility/call_traits.htm">call traits</a></nobr> to determine
|
||||||
|
the best way to declare their arguments and pass them through
|
||||||
|
to the adapted function (see <a href="#arguments">below</a>).
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Usage</h3>
|
||||||
|
|
||||||
|
<p>Usage is identical to the standard negators. For example,</p>
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
bool bad(const Foo &foo) { ... }
|
||||||
|
...
|
||||||
|
std::vector<Foo> c;
|
||||||
|
...
|
||||||
|
std::find_if(c.begin(), c.end(), boost::not1(bad));
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<h3 id="arguments">Argument Types</h3>
|
||||||
|
|
||||||
|
<p>The C++ Standard <nobr>(§20.3.5)</nobr> defines unary negate
|
||||||
|
like this (binary negate is similar):</p>
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
template <class Predicate>
|
||||||
|
class unary_negate
|
||||||
|
: public unary_function<typename Predicate::argument_type,bool> {
|
||||||
|
public:
|
||||||
|
explicit unary_negate(const Predicate& pred);
|
||||||
|
bool operator()(<strong>const typename Predicate::argument_type&</strong> x) const;
|
||||||
|
};</pre></blockquote>
|
||||||
|
|
||||||
|
<p>Note that if the Predicate's <nobr><tt>argument_type</tt></nobr> is
|
||||||
|
a reference, the type of <nobr><tt>operator()</tt>'s</nobr> argument
|
||||||
|
would be a reference to a reference. Currently this is illegal in C++
|
||||||
|
(but see the <a
|
||||||
|
href="http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#106">
|
||||||
|
C++ standard core language active issues list</a>).</p>
|
||||||
|
|
||||||
|
<p>However, if we instead defined <nobr><tt>operator()</tt></nobr>
|
||||||
|
to accept Predicate's argument_type unmodified, this would be
|
||||||
|
needlessly inefficient if it were a value type; the argument would be
|
||||||
|
copied twice - once when calling <nobr><tt>unary_negate</tt>'s</nobr>
|
||||||
|
<nobr><tt>operator()</tt></nobr>, and again when <nobr><tt>operator()</tt></nobr>
|
||||||
|
called the adapted function.</p>
|
||||||
|
|
||||||
|
<p>So how we want to declare the argument for
|
||||||
|
<nobr><tt>operator()</tt></nobr> depends on whether or not the
|
||||||
|
Predicate's <nobr><tt>argument_type</tt></nobr> is a reference. If it
|
||||||
|
is a reference, we want to declare it simply as
|
||||||
|
<nobr><tt>argument_type</tt></nobr>; if it is a value we want to
|
||||||
|
declare it as <nobr><tt>const argument_type&</tt></nobr>.
|
||||||
|
|
||||||
|
<p>The Boost <nobr><a
|
||||||
|
href="../utility/call_traits.htm">call_traits</a></nobr> class
|
||||||
|
template contains a <tt><nobr>param_type</nobr></tt> typedef, which
|
||||||
|
uses partial specialisation to make precisely this decision. If we were
|
||||||
|
to declare <nobr><tt>operator()</tt></nobr> as</p>
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
bool operator()(typename call_traits<typename Predicate::argument_type>::param_type x) const
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<p>the desired result would be achieved - we would eliminate
|
||||||
|
references to references without loss of efficiency. In fact, the
|
||||||
|
actual declaration is slightly more complicated because of the use of
|
||||||
|
function object traits, but the effect remains the same.</p>
|
||||||
|
|
||||||
|
<h3>Limitations</h3>
|
||||||
|
|
||||||
|
<p>Both the function object traits and call traits used to realise
|
||||||
|
these improvements rely on partial specialisation, these improvements
|
||||||
|
are only available on compilers that support that feature. With other
|
||||||
|
compilers, the negators in this library behave very much like those
|
||||||
|
in the Standard - <nobr><tt>ptr_fun</tt></nobr> will be required to
|
||||||
|
adapt functions, and references to references will not be avoided.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<p>Copyright © 2000 Cadenza New Zealand Ltd. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.</p>
|
||||||
|
|
||||||
|
<p>Revised 28 June 2000</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
135
ptr_fun.html
Normal file
135
ptr_fun.html
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<title>Boost Function Object Adapter Library</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body bgcolor="#FFFFFF" text="#000000">
|
||||||
|
|
||||||
|
<table border="1" bgcolor="#007F7F" cellpadding="2">
|
||||||
|
<tr>
|
||||||
|
<td bgcolor="#FFFFFF"><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" WIDTH="277" HEIGHT="86"></td>
|
||||||
|
<td><a href="../../index.htm"><font face="Arial" color="#FFFFFF"><big>Home </big></font></a></td>
|
||||||
|
<td><a href="../../libraries.htm"><font face="Arial" color="#FFFFFF"><big>Libraries </big></font></a></td>
|
||||||
|
<td><a href="../../people.htm"><font face="Arial" color="#FFFFFF"><big>People </big></font></a></td>
|
||||||
|
<td><a href="../../more/faq.htm"><font face="Arial" color="#FFFFFF"><big>FAQ </big></font></a></td>
|
||||||
|
<td><a href="../../more/index.htm"><font face="Arial" color="#FFFFFF"><big>More </big></font></a></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h1>Function Pointer Adapters</h1>
|
||||||
|
|
||||||
|
<p>The header <nobr><a
|
||||||
|
href="../../boost/functional.hpp">functional.hpp</a></nobr> provides
|
||||||
|
enhanced versions of both the function pointer adapters from the C++
|
||||||
|
Standard Library <nobr>(§ 20.3.7):</nobr></p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><tt>pointer_to_unary_function</tt></li>
|
||||||
|
<li><tt>pointer_to_binary_function</tt></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>As well as the corresponding helper function template:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><tt>ptr_fun</tt></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>However, you should not need to use the adapters in conjunction
|
||||||
|
with the adapters in this library due to our use of <a
|
||||||
|
href="function_traits.html">function object traits</a>. You will
|
||||||
|
however need to use them if your implementation fails to work properly
|
||||||
|
with our traits classes (due to lack if partial specialisation), or if
|
||||||
|
you wish to use a function object adapter from a third party.
|
||||||
|
|
||||||
|
<h3>Usage</h3>
|
||||||
|
|
||||||
|
<p>If you need to use these adapters, usage is identical to the
|
||||||
|
standard function pointer adapters. For example,</p>
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
bool bad(std::string foo) { ... }
|
||||||
|
...
|
||||||
|
std::vector<std::string> c;
|
||||||
|
...
|
||||||
|
std::vector<std::string>::iterator it
|
||||||
|
= std::find_if(c.begin(), c.end(), std::not1(boost::ptr_fun(bad)));
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<p>Note however that this library contains enhanced <a
|
||||||
|
href="negators.html">negators</a> that support function object traits,
|
||||||
|
so the line above could equally be written
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
std::vector<std::string>::iterator it
|
||||||
|
= std::find_if(c.begin(), c.end(), boost::not1(bad));
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<h3>Argument Types</h3>
|
||||||
|
|
||||||
|
<p>The standard defines
|
||||||
|
<nobr><tt>pointer_to_unary_function</tt></nobr> like this
|
||||||
|
<nobr>(§20.3.8 ¶2):</nobr>
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
template <class Arg, class Result>
|
||||||
|
class pointer_to_unary_function : public unary_function<Arg, Result> {
|
||||||
|
public:
|
||||||
|
explicit pointer_to_unary_function(Result (* f)(<strong>Arg</strong>));
|
||||||
|
Result operator()(<strong>Arg</strong> x) const;
|
||||||
|
};
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<p>Note that the argument to <nobr><tt>operator()</tt></nobr> is
|
||||||
|
exactly the same type as the argument to the wrapped function. If this
|
||||||
|
is a value type, the argument will be passed by value and copied twice.
|
||||||
|
<nobr><tt>pointer_to_binary_function</tt></nobr> has a similar problem.
|
||||||
|
|
||||||
|
<p>However, if we were to try and eliminate this inefficiency by
|
||||||
|
instead declaring the argument as <nobr><tt>const Arg&</tt></nobr>, then
|
||||||
|
if Arg were a reference type, we would have a reference to a reference,
|
||||||
|
which is currently illegal (but see <a
|
||||||
|
href="http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#106">C++
|
||||||
|
core language issue number 106)</a>
|
||||||
|
|
||||||
|
<p>So the way in which we want to declare the argument for
|
||||||
|
<nobr><tt>operator()</tt></nobr> depends on whether or not the
|
||||||
|
wrapped function's argument is a reference. If it
|
||||||
|
is a reference, we want to declare it simply as
|
||||||
|
<nobr><tt>Arg</tt></nobr>; if it is a value we want to
|
||||||
|
declare it as <nobr><tt>const Arg&</tt></nobr>.
|
||||||
|
|
||||||
|
<p>The Boost <nobr><a
|
||||||
|
href="../utility/call_traits.htm">call_traits</a></nobr> class
|
||||||
|
template contains a <tt><nobr>param_type</nobr></tt> typedef, which
|
||||||
|
uses partial specialisation to make precisely this decision. By
|
||||||
|
declaring the <nobr><tt>operator()</tt></nobr> as
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
|
Result operator()(typename call_traits<Arg>::param_type x) const
|
||||||
|
</pre></blockquote>
|
||||||
|
|
||||||
|
<p>we achieve the desired result - we improve efficiency without
|
||||||
|
generating references to references.</p>
|
||||||
|
|
||||||
|
<h3>Limitations</h3>
|
||||||
|
|
||||||
|
<p>The call traits template used to realise this improvement relies
|
||||||
|
on partial specialisation, so this improvement is only available on
|
||||||
|
compilers that support that feature. With other compilers, the
|
||||||
|
argument passed to the function will always be passed by
|
||||||
|
reference, thus generating the possibility of references to references.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<p>Copyright © 2000 Cadenza New Zealand Ltd. Permission to copy,
|
||||||
|
use, modify, sell and distribute this document is granted provided
|
||||||
|
this copyright notice appears in all copies. This document is provided
|
||||||
|
"as is" without express or implied warranty, and with no claim as to
|
||||||
|
its suitability for any purpose.</p>
|
||||||
|
|
||||||
|
<p>Revised 28 June 2000</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
Reference in New Issue
Block a user