forked from boostorg/utility
Removed docs and tests of the components moved to Boost.Core. Added links and redirections to the docs in Boost.Core.
This commit is contained in:
+15
-464
@@ -1,464 +1,15 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||
<HTML>
|
||||
<HEAD><TITLE>enable_if</TITLE>
|
||||
|
||||
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<META name="GENERATOR" content="Microsoft FrontPage 5.0">
|
||||
</HEAD>
|
||||
<BODY >
|
||||
<!--HEVEA command line is: hevea -nosymb -noiso -pedantic -v enable_if_docs_for_boost.tex -->
|
||||
<!--HTMLHEAD-->
|
||||
<!--ENDHTML-->
|
||||
<!--PREFIX <ARG ></ARG>-->
|
||||
<!--CUT DEF section 1 -->
|
||||
<BR>
|
||||
<BR>
|
||||
|
||||
|
||||
<h1>
|
||||
<img border="0" src="../../boost.png" align="center" width="277" height="86">enable_if</h1>
|
||||
<BR>
|
||||
<BR>
|
||||
Copyright 2003 Jaakko Järvi, Jeremiah Willcock, Andrew Lumsdaine.<BR>
|
||||
Copyright 2011 Matt Calabrese.<BR>
|
||||
<BR>
|
||||
<!--TOC section Introduction-->
|
||||
|
||||
<H2><A NAME="htoc1">1</A> Introduction</H2><!--SEC END -->
|
||||
|
||||
<A NAME="introduction"></A>
|
||||
The <TT>enable_if</TT> family of templates is a set of tools to allow a function template or a class template specialization
|
||||
to include or exclude itself from a set of matching functions or specializations
|
||||
based on properties of its template arguments.
|
||||
For example, one can define function templates that
|
||||
are only enabled for, and thus only match, an arbitrary set of types
|
||||
defined by a traits class. The <TT>enable_if</TT> templates can also be
|
||||
applied to enable class template specializations. Applications of
|
||||
<TT>enable_if</TT> are discussed in length
|
||||
in [<A HREF="#jarvi:03:cuj_arbitrary_overloading"><CITE>1</CITE></A>] and [<A HREF="#jarvi:03:c++typeclasses"><CITE>2</CITE></A>].<BR>
|
||||
<BR>
|
||||
<!--TOC subsection Synopsis-->
|
||||
|
||||
<H3><A NAME="htoc2">1.1</A> Synopsis</H3><!--SEC END -->
|
||||
|
||||
<A NAME="sec:synopsis"></A>
|
||||
<PRE>namespace boost {
|
||||
template <class Cond, class T = void> struct enable_if;
|
||||
template <class Cond, class T = void> struct disable_if;
|
||||
template <class Cond, class T> struct lazy_enable_if;
|
||||
template <class Cond, class T> struct lazy_disable_if;
|
||||
|
||||
template <bool B, class T = void> struct enable_if_c;
|
||||
template <bool B, class T = void> struct disable_if_c;
|
||||
template <bool B, class T> struct lazy_enable_if_c;
|
||||
template <bool B, class T> struct lazy_disable_if_c;
|
||||
}
|
||||
</PRE>
|
||||
<!--TOC subsection Background-->
|
||||
|
||||
<H3><A NAME="htoc3">1.2</A> Background</H3><!--SEC END -->
|
||||
|
||||
<A NAME="sec:background"></A>
|
||||
Sensible operation of template function overloading in C++ relies
|
||||
on the <EM>SFINAE</EM> (substitution-failure-is-not-an-error)
|
||||
principle [<A HREF="#vandevoorde2002:templates"><CITE>3</CITE></A>]: if an invalid argument
|
||||
or return type is formed during the instantiation of a function
|
||||
template, the instantiation is removed from the overload resolution
|
||||
set instead of causing a compilation error. The following example,
|
||||
taken from [<A HREF="#jarvi:03:cuj_arbitrary_overloading"><CITE>1</CITE></A>],
|
||||
demonstrates why this is important:
|
||||
<PRE>int negate(int i) { return -i; }
|
||||
|
||||
template <class F>
|
||||
typename F::result_type negate(const F& f) { return -f(); }
|
||||
|
||||
</PRE>
|
||||
Suppose the compiler encounters the call <TT>negate(1)</TT>. The first
|
||||
definition is obviously a better match, but the compiler must
|
||||
nevertheless consider (and instantiate the prototypes) of both
|
||||
definitions to find this out. Instantiating the latter definition with
|
||||
<TT>F</TT> as <TT>int</TT> would result in:
|
||||
<PRE>int::result_type negate(const int&);
|
||||
|
||||
</PRE>
|
||||
where the return type is invalid. If this were an error, adding an unrelated function template
|
||||
(that was never called) could break otherwise valid code.
|
||||
Due to the SFINAE principle the above example is not, however, erroneous.
|
||||
The latter definition of <TT>negate</TT> is simply removed from the overload resolution set.<BR>
|
||||
<BR>
|
||||
The <TT>enable_if</TT> templates are tools for controlled creation of the SFINAE
|
||||
conditions.<BR>
|
||||
<BR>
|
||||
<!--TOC section The <TT>enable_if</TT> templates-->
|
||||
|
||||
<H2><A NAME="htoc4">2</A> The <TT>enable_if</TT> templates</H2><!--SEC END -->
|
||||
|
||||
<A NAME="enable_if"></A>
|
||||
The names of the <TT>enable_if</TT> templates have three parts: an optional <TT>lazy_</TT> tag,
|
||||
either <TT>enable_if</TT> or <TT>disable_if</TT>, and an optional <TT>_c</TT> tag.
|
||||
All eight combinations of these parts are supported.
|
||||
The meaning of the <TT>lazy_</TT> tag is described in Section <A HREF="#sec:enable_if_lazy">3.3</A>.
|
||||
The second part of the name indicates whether a true condition argument should
|
||||
enable or disable the current overload.
|
||||
The third part of the name indicates whether the condition argument is a <TT>bool</TT> value
|
||||
(<TT>_c</TT> suffix), or a type containing a static <TT>bool</TT> constant named <TT>value</TT> (no suffix).
|
||||
The latter version interoperates with Boost.MPL. <BR>
|
||||
<BR>
|
||||
The definitions of <TT>enable_if_c</TT> and <TT>enable_if</TT> are as follows (we use <TT>enable_if</TT> templates
|
||||
unqualified but they are in the <TT>boost</TT> namespace).
|
||||
<PRE>template <bool B, class T = void>
|
||||
struct enable_if_c {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct enable_if_c<false, T> {};
|
||||
|
||||
template <class Cond, class T = void>
|
||||
struct enable_if : public enable_if_c<Cond::value, T> {};
|
||||
|
||||
</PRE>
|
||||
An instantiation of the <TT>enable_if_c</TT> template with the parameter
|
||||
<TT>B</TT> as <TT>true</TT> contains a member type <TT>type</TT>, defined
|
||||
to be <TT>T</TT>. If <TT>B</TT> is
|
||||
<TT>false</TT>, no such member is defined. Thus
|
||||
<TT>enable_if_c<B, T>::type</TT> is either a valid or an invalid type
|
||||
expression, depending on the value of <TT>B</TT>.
|
||||
When valid, <TT>enable_if_c<B, T>::type</TT> equals <TT>T</TT>.
|
||||
The <TT>enable_if_c</TT> template can thus be used for controlling when functions are considered for
|
||||
overload resolution and when they are not.
|
||||
For example, the following function is defined for all arithmetic types (according to the
|
||||
classification of the <A HREF="../type_traits/index.html">Boost type_traits library</A>):
|
||||
<PRE>template <class T>
|
||||
typename enable_if_c<boost::is_arithmetic<T>::value, T>::type
|
||||
foo(T t) { return t; }
|
||||
|
||||
</PRE>
|
||||
The <TT>disable_if_c</TT> template is provided as well, and has the
|
||||
same functionality as <TT>enable_if_c</TT> except for the negated condition. The following
|
||||
function is enabled for all non-arithmetic types.
|
||||
<PRE>template <class T>
|
||||
typename disable_if_c<boost::is_arithmetic<T>::value, T>::type
|
||||
bar(T t) { return t; }
|
||||
|
||||
</PRE>
|
||||
For easier syntax in some cases and interoperation with Boost.MPL we provide versions of
|
||||
the <TT>enable_if</TT> templates taking any type with a <TT>bool</TT> member constant named
|
||||
<TT>value</TT> as the condition argument.
|
||||
The MPL <TT>bool_</TT>, <TT>and_</TT>, <TT>or_</TT>, and <TT>not_</TT> templates are likely to be
|
||||
useful for creating such types. Also, the traits classes in the Boost.Type_traits library
|
||||
follow this convention.
|
||||
For example, the above example function <TT>foo</TT> can be alternatively written as:
|
||||
<PRE>template <class T>
|
||||
typename enable_if<boost::is_arithmetic<T>, T>::type
|
||||
foo(T t) { return t; }
|
||||
|
||||
</PRE>
|
||||
|
||||
<!--TOC section Using <TT>enable_if</TT>-->
|
||||
|
||||
<H2><A NAME="htoc5">3</A> Using <TT>enable_if</TT></H2><!--SEC END -->
|
||||
|
||||
<A NAME="sec:using_enable_if"></A>
|
||||
The <TT>enable_if</TT> templates are defined in
|
||||
<TT>boost/utility/enable_if.hpp</TT>, which is included by <TT>boost/utility.hpp</TT>.<BR>
|
||||
<BR>
|
||||
With respect to function templates, <TT>enable_if</TT> can be used in multiple different ways:
|
||||
|
||||
<UL>
|
||||
<LI>As the return type of an instantiatied function
|
||||
<LI>As an extra parameter of an instantiated function
|
||||
<LI>As an extra template parameter (useful only in a compiler that supports C++0x default
|
||||
arguments for function template parameters, see <A href="#sec:enable_if_0x">Enabling function
|
||||
templates in C++0x</a> for details)
|
||||
</UL>
|
||||
|
||||
In the previous section, the return type form of <TT>enable_if</TT> was shown. As an example
|
||||
of using the form of <TT>enable_if</TT> that works via an extra function parameter, the
|
||||
<TT>foo</TT> function in the previous section could also be written
|
||||
as:
|
||||
<PRE>template <class T>
|
||||
T foo(T t, typename enable_if<boost::is_arithmetic<T> >::type* dummy = 0);
|
||||
|
||||
</PRE>Hence, an extra parameter of type <TT>void*</TT> is added, but it is given
|
||||
a default value to keep the parameter hidden from client code.
|
||||
Note that the second template argument was not given to <TT>enable_if</TT>, as the default
|
||||
<TT>void</TT> gives the desired behavior.<BR>
|
||||
<BR>
|
||||
Which way to write the enabler is largely a matter of taste, but for certain functions, only a
|
||||
subset of the options is possible:
|
||||
<UL><LI>
|
||||
Many operators have a fixed number of arguments, thus <TT>enable_if</TT> must be used either in the
|
||||
return type or in an extra template parameter.
|
||||
<LI>Functions that have a variadic parameter list must use either the return type form or an extra
|
||||
template parameter.
|
||||
<LI>Constructors do not have a return type so you must use either an extra function parameter or an
|
||||
extra template parameter.
|
||||
<LI>Constructors that have a variadic parameter list must an extra template parameter.
|
||||
<LI>Conversion operators can only be written with an extra template parameter.
|
||||
</UL>
|
||||
<!--TOC subsection Enabling function templates in C++0x-->
|
||||
|
||||
<A NAME="sec:enable_if_0x"></A>
|
||||
<H3><A NAME="htoc6">3.1</A> Enabling function templates in C++0x</H3><!--SEC END -->
|
||||
|
||||
In a compiler which supports C++0x default arguments for function template parameters, you can
|
||||
enable and disable function templates by adding an additional template parameter. This approach
|
||||
works in all situations where you would use either the return type form of <TT>enable_if</TT> or
|
||||
the function parameter form, including operators, constructors, variadic function templates, and
|
||||
even overloaded conversion operations.
|
||||
|
||||
As an example:
|
||||
|
||||
<PRE>#include <boost/type_traits/is_arithmetic.hpp>
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
class test
|
||||
{
|
||||
public:
|
||||
// A constructor that works for any argument list of size 10
|
||||
template< class... T
|
||||
, typename boost::enable_if_c< sizeof...( T ) == 10, int >::type = 0
|
||||
>
|
||||
test( T&&... );
|
||||
|
||||
// A conversion operation that can convert to any arithmetic type
|
||||
template< class T
|
||||
, typename boost::enable_if< boost::is_arithmetic< T >, int >::type = 0
|
||||
>
|
||||
operator T() const;
|
||||
|
||||
// A conversion operation that can convert to any pointer type
|
||||
template< class T
|
||||
, typename boost::enable_if< boost::is_pointer< T >, int >::type = 0
|
||||
>
|
||||
operator T() const;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
// Works
|
||||
test test_( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 );
|
||||
|
||||
// Fails as expected
|
||||
test fail_construction( 1, 2, 3, 4, 5 );
|
||||
|
||||
// Works by calling the conversion operator enabled for arithmetic types
|
||||
int arithmetic_object = test_;
|
||||
|
||||
// Works by calling the conversion operator enabled for pointer types
|
||||
int* pointer_object = test_;
|
||||
|
||||
// Fails as expected
|
||||
struct {} fail_conversion = test_;
|
||||
}
|
||||
|
||||
</PRE>
|
||||
|
||||
<!--TOC subsection Enabling template class specializations-->
|
||||
|
||||
<H3><A NAME="htoc7">3.2</A> Enabling template class specializations</H3><!--SEC END -->
|
||||
|
||||
<A NAME="sec:enable_if_classes"></A>
|
||||
Class template specializations can be enabled or disabled with <TT>enable_if</TT>.
|
||||
One extra template parameter needs to be added for the enabler expressions.
|
||||
This parameter has the default value <TT>void</TT>.
|
||||
For example:
|
||||
<PRE>template <class T, class Enable = void>
|
||||
class A { ... };
|
||||
|
||||
template <class T>
|
||||
class A<T, typename enable_if<is_integral<T> >::type> { ... };
|
||||
|
||||
template <class T>
|
||||
class A<T, typename enable_if<is_float<T> >::type> { ... };
|
||||
|
||||
</PRE>Instantiating <TT>A</TT> with any integral type matches the first specialization,
|
||||
whereas any floating point type matches the second one. All other types
|
||||
match the primary template.
|
||||
The condition can be any compile-time boolean expression that depends on the
|
||||
template arguments of the class.
|
||||
Note that again, the second argument to <TT>enable_if</TT> is not needed; the default (<TT>void</TT>)
|
||||
is the correct value.<BR>
|
||||
<BR>
|
||||
<!--TOC subsection Overlapping enabler conditions-->
|
||||
|
||||
<H3><A NAME="htoc8">3.3</A> Overlapping enabler conditions</H3><!--SEC END -->
|
||||
|
||||
<A NAME="sec:overlapping_conditions"></A>
|
||||
Once the compiler has examined the enabling conditions and included the
|
||||
function into the overload resolution set, normal C++ overload resolution
|
||||
rules are used to select the best matching function.
|
||||
In particular, there is no ordering between enabling conditions.
|
||||
Function templates with enabling conditions that are not mutually exclusive can
|
||||
lead to ambiguities. For example:
|
||||
<PRE>template <class T>
|
||||
typename enable_if<boost::is_integral<T>, void>::type
|
||||
foo(T t) {}
|
||||
|
||||
template <class T>
|
||||
typename enable_if<boost::is_arithmetic<T>, void>::type
|
||||
foo(T t) {}
|
||||
|
||||
</PRE>
|
||||
All integral types are also arithmetic. Therefore, say, for the call <TT>foo(1)</TT>,
|
||||
both conditions are true and both functions are thus in the overload resolution set.
|
||||
They are both equally good matches and thus ambiguous.
|
||||
Of course, more than one enabling condition can be simultaneously true as long as
|
||||
other arguments disambiguate the functions.<BR>
|
||||
<BR>
|
||||
The above discussion applies to using <TT>enable_if</TT> in class template
|
||||
partial specializations as well.<BR>
|
||||
<BR>
|
||||
<!--TOC subsection Lazy <TT>enable_if</TT>-->
|
||||
|
||||
<H3><A NAME="htoc9">3.4</A> Lazy <TT>enable_if</TT></H3><!--SEC END -->
|
||||
|
||||
<A NAME="sec:enable_if_lazy"></A>
|
||||
In some cases it is necessary to avoid instantiating part of a
|
||||
function signature unless an enabling condition is true. For example:
|
||||
<PRE>template <class T, class U> class mult_traits;
|
||||
|
||||
template <class T, class U>
|
||||
typename enable_if<is_multipliable<T, U>, typename mult_traits<T, U>::type>::type
|
||||
operator*(const T& t, const U& u) { ... }
|
||||
|
||||
</PRE>Assume the class template <TT>mult_traits</TT> is a traits class defining
|
||||
the resulting type of a multiplication operator. The <TT>is_multipliable</TT> traits
|
||||
class specifies for which types to enable the operator. Whenever
|
||||
<TT>is_multipliable<A, B>::value</TT> is <TT>true</TT> for some types <TT>A</TT> and <TT>B</TT>,
|
||||
then <TT>mult_traits<A, B>::type</TT> is defined.<BR>
|
||||
<BR>
|
||||
Now, trying to invoke (some other overload) of <TT>operator*</TT> with, say, operand types <TT>C</TT> and <TT>D</TT>
|
||||
for which <TT>is_multipliable<C, D>::value</TT> is <TT>false</TT>
|
||||
and <TT>mult_traits<C, D>::type</TT> is not defined is an error on some compilers.
|
||||
The SFINAE principle is not applied because
|
||||
the invalid type occurs as an argument to another template. The <TT>lazy_enable_if</TT>
|
||||
and <TT>lazy_disable_if</TT> templates (and their <TT>_c</TT> versions) can be used in such
|
||||
situations:
|
||||
<PRE>template<class T, class U>
|
||||
typename lazy_enable_if<is_multipliable<T, U>, mult_traits<T, U> >::type
|
||||
operator*(const T& t, const U& u) { ... }
|
||||
|
||||
</PRE>The second argument of <TT>lazy_enable_if</TT> must be a class type
|
||||
that defines a nested type named <TT>type</TT> whenever the first
|
||||
parameter (the condition) is true.<BR>
|
||||
<BR>
|
||||
<!--TOC paragraph Note-->
|
||||
|
||||
<H5>Note</H5><!--SEC END -->
|
||||
|
||||
Referring to one member type or static constant in a traits class
|
||||
causes all of the members (type and static constant) of that
|
||||
specialization to be instantiated. Therefore, if your traits classes
|
||||
can sometimes contain invalid types, you should use two distinct
|
||||
templates for describing the conditions and the type mappings. In the
|
||||
above example, <TT>is_multipliable<T, U>::value</TT> defines when
|
||||
<TT>mult_traits<T, U>::type</TT> is valid.<BR>
|
||||
<BR>
|
||||
<!--TOC subsection Compiler workarounds-->
|
||||
|
||||
<H3><A NAME="htoc10">3.5</A> Compiler workarounds</H3><!--SEC END -->
|
||||
|
||||
<A NAME="sec:workarounds"></A>
|
||||
Some compilers flag functions as ambiguous if the only distinguishing factor is a different
|
||||
condition in an enabler (even though the functions could never be ambiguous). For example,
|
||||
some compilers (e.g. GCC 3.2) diagnose the following two functions as ambiguous:
|
||||
<PRE>template <class T>
|
||||
typename enable_if<boost::is_arithmetic<T>, T>::type
|
||||
foo(T t);
|
||||
|
||||
template <class T>
|
||||
typename disable_if<boost::is_arithmetic<T>, T>::type
|
||||
foo(T t);
|
||||
|
||||
</PRE>Two workarounds can be applied:
|
||||
<UL><LI>
|
||||
Use an extra dummy parameter which disambiguates the functions. Use a default value for
|
||||
it to hide the parameter from the caller. For example:
|
||||
<PRE>template <int> struct dummy { dummy(int) {} };
|
||||
|
||||
template <class T>
|
||||
typename enable_if<boost::is_arithmetic<T>, T>::type
|
||||
foo(T t, dummy<0> = 0);
|
||||
|
||||
template <class T>
|
||||
typename disable_if<boost::is_arithmetic<T>, T>::type
|
||||
foo(T t, dummy<1> = 0);
|
||||
</PRE><BR>
|
||||
<BR>
|
||||
<LI>Define the functions in different namespaces and bring them into a common
|
||||
namespace with <TT>using</TT> declarations:
|
||||
<PRE>namespace A {
|
||||
template <class T>
|
||||
typename enable_if<boost::is_arithmetic<T>, T>::type
|
||||
foo(T t);
|
||||
}
|
||||
|
||||
namespace B {
|
||||
template <class T>
|
||||
typename disable_if<boost::is_arithmetic<T>, T>::type
|
||||
foo(T t);
|
||||
}
|
||||
|
||||
using A::foo;
|
||||
using B::foo;
|
||||
|
||||
</PRE>
|
||||
Note that the second workaround above cannot be used for member
|
||||
templates. On the other hand, operators do not accept extra arguments,
|
||||
which makes the first workaround unusable. As the net effect,
|
||||
neither of the workarounds are of assistance for templated operators that
|
||||
need to be defined as member functions (assignment and
|
||||
subscript operators).
|
||||
</UL>
|
||||
<!--TOC section Acknowledgements-->
|
||||
|
||||
<H2><A NAME="htoc11">4</A> Acknowledgements</H2><!--SEC END -->
|
||||
|
||||
We are grateful to Howard Hinnant, Jason Shirk, Paul Mensonides, and Richard
|
||||
Smith whose findings have influenced the library.<BR>
|
||||
<BR>
|
||||
<!--TOC section References-->
|
||||
|
||||
<H2>References</H2><!--SEC END -->
|
||||
<DL COMPACT=compact><DT><A NAME="jarvi:03:cuj_arbitrary_overloading"><FONT COLOR=purple>[1]</FONT></A><DD>
|
||||
Jaakko Järvi, Jeremiah Willcock, Howard Hinnant, and Andrew Lumsdaine.
|
||||
Function overloading based on arbitrary properties of types.
|
||||
<EM>C/C++ Users Journal</EM>, 21(6):25--32, June 2003.<BR>
|
||||
<BR>
|
||||
<DT><A NAME="jarvi:03:c++typeclasses"><FONT COLOR=purple>[2]</FONT></A><DD>
|
||||
Jaakko Järvi, Jeremiah Willcock, and Andrew Lumsdaine.
|
||||
Concept-controlled polymorphism.
|
||||
In Frank Pfennig and Yannis Smaragdakis, editors, <EM>Generative
|
||||
Programming and Component Engineering</EM>, volume 2830 of <EM>LNCS</EM>, pages
|
||||
228--244. Springer Verlag, September 2003.<BR>
|
||||
<BR>
|
||||
<DT><A NAME="vandevoorde2002:templates"><FONT COLOR=purple>[3]</FONT></A><DD>
|
||||
David Vandevoorde and Nicolai M. Josuttis.
|
||||
<EM>C++ Templates: The Complete Guide</EM>.
|
||||
Addison-Wesley, 2002.</DL>
|
||||
|
||||
<hr/>
|
||||
<p>Copyright Jaakko Järvi<sup>*</sup>, Jeremiah Willcock<sup>*</sup>, Andrew Lumsdaine<sup>*</sup>, Matt Calabrese<BR>
|
||||
<EM>{jajarvi|jewillco|lums}@osl.iu.edu, rivorus@gmail.com</EM><BR>
|
||||
<sup>*</sup>Indiana University<BR>
|
||||
Open Systems Lab<br/>
|
||||
Use, modification and distribution are subject to the
|
||||
Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt
|
||||
or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
http://www.boost.org/LICENSE_1_0.txt
|
||||
</a>).
|
||||
</p>
|
||||
<!--HTMLFOOT-->
|
||||
<!--ENDHTML-->
|
||||
<!--FOOTER-->
|
||||
<HR SIZE=2>
|
||||
<BLOCKQUOTE><EM>This document was translated from L<sup>A</sup>T<sub>E</sub>X by
|
||||
</EM><A HREF="http://pauillac.inria.fr/~maranget/hevea/index.html"><EM>H<FONT SIZE=2><sup>E</sup></FONT>V<FONT SIZE=2><sup>E</sup></FONT>A</EM></A><EM>.
|
||||
</EM></BLOCKQUOTE>
|
||||
</BODY>
|
||||
</HTML>
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv=refresh content="0; URL=../core/doc/html/core/enable_if.html">
|
||||
<title>Automatic redirection</title>
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="../core/doc/html/core/enable_if.html">enable_if.html</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>
|
||||
|
||||
Reference in New Issue
Block a user