mirror of
https://github.com/boostorg/intrusive.git
synced 2025-08-03 14:34:44 +02:00
Introducing allocator_traits and pointer_traits changes into several libraries.
[SVN r76107]
This commit is contained in:
@@ -2321,16 +2321,8 @@ have the following features:
|
||||
* It must have the same ownership semantics as a raw pointer. This means that
|
||||
resource management smart pointers (like `boost::shared_ptr`) can't be used.
|
||||
|
||||
The conversion from the smart pointer to a raw pointer must be implemented following
|
||||
Boost smart pointer `detail::get_pointer()` function. This function will be found using
|
||||
ADL. For example, for `boost::interprocess::offset_ptr`, `detail::get_pointer` is defined
|
||||
as follows:
|
||||
|
||||
[c++]
|
||||
|
||||
template<class T>
|
||||
T * detail::get_pointer(boost::interprocess::offset_ptr<T> const & p)
|
||||
{ return p.get(); }
|
||||
The conversion from the smart pointer to a raw pointer will be implemented as a recursive call to
|
||||
`operator->()` until the function returns a raw pointer.
|
||||
|
||||
[endsect]
|
||||
|
||||
@@ -3072,7 +3064,7 @@ achieve this using [*Boost.Intrusive] predefined hooks. Now, instead of using
|
||||
|
||||
[c++]
|
||||
|
||||
#include <boost/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
#include <boost/intrusive/link_mode.hpp>
|
||||
|
||||
struct my_value_traits
|
||||
@@ -3081,8 +3073,10 @@ achieve this using [*Boost.Intrusive] predefined hooks. Now, instead of using
|
||||
typedef implementation_defined value_type;
|
||||
typedef node_traits::node_ptr node_ptr;
|
||||
typedef node_traits::const_node_ptr const_node_ptr;
|
||||
typedef boost::pointer_to_other<node_ptr, value_type>::type pointer;
|
||||
typedef boost::pointer_to_other<node_ptr, const value_type>::type const_pointer;
|
||||
typedef boost::intrusive::pointer_traits<node_ptr>::rebind_traits
|
||||
<value_type>::type::pointer pointer;
|
||||
typedef boost::intrusive::pointer_traits<node_ptr>::rebind_traits
|
||||
<const value_type>::type::pointer const_pointer;
|
||||
|
||||
static const link_mode_type link_mode = some_linking_policy;
|
||||
|
||||
@@ -3126,14 +3120,13 @@ Let's explain each type and function:
|
||||
* [*['pointer]]: The type of a pointer to a `value_type`. It must be the same pointer type
|
||||
as `node_ptr`: If `node_ptr` is `node*`, `pointer` must be `value_type*`. If
|
||||
`node_ptr` is `smart_ptr<node_traits::node>`, `pointer` must be `smart_ptr<value_type>`.
|
||||
This can be generically achieved using `boost::pointer_to_other` utility from [*Boost SmartPointers]
|
||||
This can be generically achieved using `boost::intrusive::pointer_traits` (portable implementation of C++11
|
||||
`std::pointer_traits`) or `boost::pointer_to_other` utility from [*Boost SmartPointers]
|
||||
defined in `<boost/pointer_to_other.hpp>`.
|
||||
|
||||
* [*['const_pointer]]: The type of a pointer to a `const value_type`. It must be the same pointer type
|
||||
as `node_ptr`: If `node_ptr` is `node*`, `const_pointer` must be `const value_type*`. If
|
||||
`node_ptr` is `smart_ptr<node_traits::node>`, `const_pointer` must be `smart_ptr<const value_type>`
|
||||
This can be generically achieved using `boost::pointer_to_other` utility from [*Boost SmartPointers]
|
||||
defined in `<boost/pointer_to_other.hpp>`.
|
||||
`node_ptr` is `smart_ptr<node_traits::node>`, `const_pointer` must be `smart_ptr<const value_type>`.
|
||||
|
||||
* [*['link_mode]]: Indicates that `value_traits` needs some additional work or checks from the
|
||||
container. The types are enumerations defined in the `link_mode.hpp` header.
|
||||
@@ -3568,7 +3561,7 @@ These are the times in microseconds for each case, and the normalized time:
|
||||
[[`normal_link` intrusive list] [5000 / 22500] [1 / 1]]
|
||||
[[`safe_link` intrusive list] [7812 / 32187] [1.56 / 1.43]]
|
||||
[[`auto_unlink` intrusive list] [10156 / 41562] [2.03 / 1.84]]
|
||||
[[Standard list] [76875 / 97500] [5.37 / 4.33]]
|
||||
[[Standard list] [26875 / 97500] [5.37 / 4.33]]
|
||||
[[Standard compact pointer list] [76406 / 86718] [15.28 / 3.85]]
|
||||
[[Standard disperse pointer list] [146562 / 175625] [29.31 / 7.80]]
|
||||
]
|
||||
|
BIN
proj/vc7ide/Intrusive.ncb
Normal file
BIN
proj/vc7ide/Intrusive.ncb
Normal file
Binary file not shown.
@@ -1,24 +1,4 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 8.00
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "list", "list\list.vcproj", "{977B61B4-9968-497C-9F0B-24A8145473B8}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slist", "slist\slist.vcproj", "{5A02061D-3728-4C49-AFC8-0130C1F161C0}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "multiset", "multiset\multiset.vcproj", "{961F0E06-C092-4AF7-ABC5-2A49999F3B79}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_intrusivelib", "_intrusivelib\_intrusivelib.vcproj", "{90F3C5BD-8E6C-4629-BC71-A1009EC88059}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "set", "set\set.vcproj", "{960E01F6-92C1-F74A-BCA5-2A9F3B994979}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unordered_set", "unordered_set\unordered_set.vcproj", "{90E701E6-2C91-F4A7-BA6C-A9F3B0949279}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
@@ -99,32 +79,42 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "function_hook", "function_h
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pointer_traits", "pointer_traits\pointer_traits.vcproj", "{7679B41B-F2B4-9176-CB81-35449467B435}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "list", "list\list.vcproj", "{977B61B4-9968-497C-9F0B-24A8145473B8}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slist", "slist\slist.vcproj", "{5A02061D-3728-4C49-AFC8-0130C1F161C0}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "multiset", "multiset\multiset.vcproj", "{961F0E06-C092-4AF7-ABC5-2A49999F3B79}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_intrusivelib", "_intrusivelib\_intrusivelib.vcproj", "{90F3C5BD-8E6C-4629-BC71-A1009EC88059}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "set", "set\set.vcproj", "{960E01F6-92C1-F74A-BCA5-2A9F3B994979}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "has_member_function_callable_with", "has_member_function_callable_with\has_member_function_callable_with.vcproj", "{3579B1A4-02AB-5489-CB81-957B14032465}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
Debug = Debug
|
||||
Release = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectDependencies) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{977B61B4-9968-497C-9F0B-24A8145473B8}.Debug.ActiveCfg = Debug|Win32
|
||||
{977B61B4-9968-497C-9F0B-24A8145473B8}.Debug.Build.0 = Debug|Win32
|
||||
{977B61B4-9968-497C-9F0B-24A8145473B8}.Release.ActiveCfg = Release|Win32
|
||||
{977B61B4-9968-497C-9F0B-24A8145473B8}.Release.Build.0 = Release|Win32
|
||||
{5A02061D-3728-4C49-AFC8-0130C1F161C0}.Debug.ActiveCfg = Debug|Win32
|
||||
{5A02061D-3728-4C49-AFC8-0130C1F161C0}.Debug.Build.0 = Debug|Win32
|
||||
{5A02061D-3728-4C49-AFC8-0130C1F161C0}.Release.ActiveCfg = Release|Win32
|
||||
{5A02061D-3728-4C49-AFC8-0130C1F161C0}.Release.Build.0 = Release|Win32
|
||||
{961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Debug.ActiveCfg = Debug|Win32
|
||||
{961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Debug.Build.0 = Debug|Win32
|
||||
{961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Release.ActiveCfg = Release|Win32
|
||||
{961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Release.Build.0 = Release|Win32
|
||||
{90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Debug.ActiveCfg = Debug|Win32
|
||||
{90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Debug.Build.0 = Debug|Win32
|
||||
{90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Release.ActiveCfg = Release|Win32
|
||||
{90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Release.Build.0 = Release|Win32
|
||||
{960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Debug.ActiveCfg = Debug|Win32
|
||||
{960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Debug.Build.0 = Debug|Win32
|
||||
{960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Release.ActiveCfg = Release|Win32
|
||||
{960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Release.Build.0 = Release|Win32
|
||||
{90E701E6-2C91-F4A7-BA6C-A9F3B0949279}.Debug.ActiveCfg = Debug|Win32
|
||||
{90E701E6-2C91-F4A7-BA6C-A9F3B0949279}.Debug.Build.0 = Debug|Win32
|
||||
{90E701E6-2C91-F4A7-BA6C-A9F3B0949279}.Release.ActiveCfg = Release|Win32
|
||||
@@ -205,6 +195,34 @@ Global
|
||||
{761A79B4-9968-CB81-F02B-2A4497345475}.Debug.Build.0 = Debug|Win32
|
||||
{761A79B4-9968-CB81-F02B-2A4497345475}.Release.ActiveCfg = Release|Win32
|
||||
{761A79B4-9968-CB81-F02B-2A4497345475}.Release.Build.0 = Release|Win32
|
||||
{7679B41B-F2B4-9176-CB81-35449467B435}.Debug.ActiveCfg = Debug|Win32
|
||||
{7679B41B-F2B4-9176-CB81-35449467B435}.Debug.Build.0 = Debug|Win32
|
||||
{7679B41B-F2B4-9176-CB81-35449467B435}.Release.ActiveCfg = Release|Win32
|
||||
{7679B41B-F2B4-9176-CB81-35449467B435}.Release.Build.0 = Release|Win32
|
||||
{977B61B4-9968-497C-9F0B-24A8145473B8}.Debug.ActiveCfg = Debug|Win32
|
||||
{977B61B4-9968-497C-9F0B-24A8145473B8}.Debug.Build.0 = Debug|Win32
|
||||
{977B61B4-9968-497C-9F0B-24A8145473B8}.Release.ActiveCfg = Release|Win32
|
||||
{977B61B4-9968-497C-9F0B-24A8145473B8}.Release.Build.0 = Release|Win32
|
||||
{5A02061D-3728-4C49-AFC8-0130C1F161C0}.Debug.ActiveCfg = Debug|Win32
|
||||
{5A02061D-3728-4C49-AFC8-0130C1F161C0}.Debug.Build.0 = Debug|Win32
|
||||
{5A02061D-3728-4C49-AFC8-0130C1F161C0}.Release.ActiveCfg = Release|Win32
|
||||
{5A02061D-3728-4C49-AFC8-0130C1F161C0}.Release.Build.0 = Release|Win32
|
||||
{961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Debug.ActiveCfg = Debug|Win32
|
||||
{961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Debug.Build.0 = Debug|Win32
|
||||
{961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Release.ActiveCfg = Release|Win32
|
||||
{961F0E06-C092-4AF7-ABC5-2A49999F3B79}.Release.Build.0 = Release|Win32
|
||||
{90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Debug.ActiveCfg = Debug|Win32
|
||||
{90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Debug.Build.0 = Debug|Win32
|
||||
{90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Release.ActiveCfg = Release|Win32
|
||||
{90F3C5BD-8E6C-4629-BC71-A1009EC88059}.Release.Build.0 = Release|Win32
|
||||
{960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Debug.ActiveCfg = Debug|Win32
|
||||
{960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Debug.Build.0 = Debug|Win32
|
||||
{960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Release.ActiveCfg = Release|Win32
|
||||
{960E01F6-92C1-F74A-BCA5-2A9F3B994979}.Release.Build.0 = Release|Win32
|
||||
{3579B1A4-02AB-5489-CB81-957B14032465}.Debug.ActiveCfg = Debug|Win32
|
||||
{3579B1A4-02AB-5489-CB81-957B14032465}.Debug.Build.0 = Debug|Win32
|
||||
{3579B1A4-02AB-5489-CB81-957B14032465}.Release.ActiveCfg = Release|Win32
|
||||
{3579B1A4-02AB-5489-CB81-957B14032465}.Release.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
|
@@ -154,6 +154,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\..\..\boost\intrusive\pointer_plus_bits.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\..\boost\intrusive\pointer_traits.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\..\boost\intrusive\rbtree.hpp">
|
||||
</File>
|
||||
@@ -244,6 +247,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\..\..\boost\intrusive\detail\generic_hook.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\..\boost\intrusive\detail\has_member_function_callable_with.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\..\boost\intrusive\detail\hashtable_node.hpp">
|
||||
</File>
|
||||
@@ -253,6 +259,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\..\..\boost\intrusive\detail\list_node.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\..\boost\intrusive\detail\memory_util.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\..\boost\intrusive\detail\mpl.hpp">
|
||||
</File>
|
||||
@@ -260,7 +269,7 @@
|
||||
RelativePath="..\..\..\..\..\boost\intrusive\detail\parent_from_member.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\..\boost\intrusive\detail\pointer_to_other.hpp">
|
||||
RelativePath="..\..\..\..\..\boost\intrusive\detail\preprocessor.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\..\boost\intrusive\detail\rbtree_node.hpp">
|
||||
|
@@ -0,0 +1,133 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="has_member_function_callable_with"
|
||||
ProjectGUID="{3579B1A4-02AB-5489-CB81-957B14032465}"
|
||||
RootNamespace="virtual_base"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../../../../../"
|
||||
PreprocessorDefinitions="BOOST_DATE_TIME_NO_LIB"
|
||||
GeneratePreprocessedFile="0"
|
||||
KeepComments="FALSE"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="5"
|
||||
DisableLanguageExtensions="FALSE"
|
||||
TreatWChar_tAsBuiltInType="TRUE"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="4"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/has_member_function_callable_with.exe"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/has_member_function_callable_with.pdb"
|
||||
GenerateMapFile="TRUE"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="../../../../../"
|
||||
PreprocessorDefinitions="BOOST_DATE_TIME_NO_LIB"
|
||||
RuntimeLibrary="4"
|
||||
DisableLanguageExtensions="FALSE"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/has_member_function_callable_with.exe"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{77B513CF-A736-6476-7AB5-D4AB7228A73C}">
|
||||
<File
|
||||
RelativePath="..\..\..\test\has_member_function_callable_with.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
133
proj/vc7ide/pointer_traits/pointer_traits.vcproj
Normal file
133
proj/vc7ide/pointer_traits/pointer_traits.vcproj
Normal file
@@ -0,0 +1,133 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="pointer_traits"
|
||||
ProjectGUID="{7679B41B-F2B4-9176-CB81-35449467B435}"
|
||||
RootNamespace="pointer_traits"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../../../../../"
|
||||
PreprocessorDefinitions="BOOST_DATE_TIME_NO_LIB"
|
||||
GeneratePreprocessedFile="0"
|
||||
KeepComments="FALSE"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="5"
|
||||
DisableLanguageExtensions="FALSE"
|
||||
TreatWChar_tAsBuiltInType="TRUE"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="4"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/pointer_traits.exe"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/pointer_traits.pdb"
|
||||
GenerateMapFile="TRUE"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="../../../../../"
|
||||
PreprocessorDefinitions="BOOST_DATE_TIME_NO_LIB"
|
||||
RuntimeLibrary="4"
|
||||
DisableLanguageExtensions="FALSE"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/pointer_traits.exe"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4F537F31-AB85-7644-A616-25727F35FA5F}">
|
||||
<File
|
||||
RelativePath="..\..\..\test\pointer_traits_test.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
@@ -15,6 +15,9 @@
|
||||
-> Document incremental<> option better
|
||||
-> Assure stable order for optimize_multikey and inverse order otherwise
|
||||
-> add an option to unordered containers to get O(1) traversal and begin()/end() even with very low load factors
|
||||
-> Take all pointers by const reference to optimize shared memory pointers
|
||||
-> Return pointers by const reference if node traits return them by const reference to optimize shared memory pointers
|
||||
-> Detect call signatures by has_member_function_callable_with instead of exact match to allow taking by const reference
|
||||
|
||||
|
||||
The article explains it quite well: Linear Hashing The cost of hash table expansion is spread out across each hash table insertion operation, as opposed to being incurred all at once. Linear hashing is therefore well suited for interactive applications.
|
||||
@@ -27,3 +30,4 @@ http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1456.html
|
||||
|
||||
Now, intrusive containers don't allocate memory at all, so incremental rehashing must be trigered by the user using
|
||||
"incremental_rehash(bool)" (use an additional bucket, that is, incremental rehash) and "incremental_rehash(bucket_traits)" (to update the new bucket array with an array that should be twice/half the size of the previous one). I admit that this is not explained at all with an example, so I will note this issue in my to do list.
|
||||
|
||||
|
@@ -12,7 +12,7 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/avl_set.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
#include "itestvalue.hpp"
|
||||
#include "smart_ptr.hpp"
|
||||
#include "generic_multiset_test.hpp"
|
||||
|
@@ -29,7 +29,7 @@ class delete_disposer
|
||||
{
|
||||
typedef typename std::iterator_traits<Pointer>::value_type value_type;
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(( detail::is_same<T, value_type>::value ));
|
||||
delete detail::boost_intrusive_get_pointer(p);
|
||||
delete boost::intrusive::detail::to_raw_pointer(p);
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -16,6 +16,7 @@
|
||||
#include <boost/intrusive/splay_set.hpp>
|
||||
#include <boost/intrusive/avl_set.hpp>
|
||||
#include <boost/intrusive/sg_set.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
#include "smart_ptr.hpp"
|
||||
#include <vector>
|
||||
|
||||
@@ -78,7 +79,8 @@ int main()
|
||||
List my_list;
|
||||
Slist my_slist;
|
||||
Set my_set;
|
||||
USet my_uset(USet::bucket_traits(buckets, 100));
|
||||
USet my_uset(USet::bucket_traits(pointer_traits<USet::bucket_ptr>::pointer_to(*buckets), 100));
|
||||
|
||||
AvlSet my_avlset;
|
||||
SplaySet my_splayset;
|
||||
SgSet my_sgset;
|
||||
|
@@ -13,7 +13,7 @@
|
||||
#include <boost/intrusive/slist.hpp>
|
||||
#include <boost/intrusive/rbtree.hpp>
|
||||
#include <boost/intrusive/hashtable.hpp>
|
||||
#include <boost/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
@@ -40,15 +40,16 @@ const int NumElements = 100;
|
||||
template<class NodeTraits>
|
||||
struct external_traits
|
||||
{
|
||||
typedef NodeTraits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef typename node_traits::const_node_ptr const_node_ptr;
|
||||
typedef MyClass value_type;
|
||||
typedef typename boost::pointer_to_other
|
||||
<node_ptr, MyClass>::type pointer;
|
||||
typedef typename boost::pointer_to_other
|
||||
<node_ptr, const MyClass>::type const_pointer;
|
||||
typedef NodeTraits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef typename node_traits::const_node_ptr const_node_ptr;
|
||||
typedef MyClass value_type;
|
||||
typedef typename pointer_traits<node_ptr>::
|
||||
template rebind_pointer<MyClass>::type pointer;
|
||||
typedef typename pointer_traits<node_ptr>::
|
||||
template rebind_pointer
|
||||
<const MyClass>::type const_pointer;
|
||||
static const link_mode_type link_mode = normal_link;
|
||||
|
||||
external_traits(pointer values, std::size_t NumElem)
|
||||
|
@@ -325,17 +325,14 @@ void test_generic_assoc<ValueTraits, ContainerDefiner>::test_rebalance
|
||||
>::type assoc_type;
|
||||
typedef std::vector<value_type> orig_set_t;
|
||||
typedef typename orig_set_t::iterator iterator_t;
|
||||
std::size_t num_values;
|
||||
orig_set_t original_testset;
|
||||
{
|
||||
assoc_type testset (values.begin(), values.end());
|
||||
num_values = testset.size();
|
||||
original_testset.insert(original_testset.end(), testset.begin(), testset.end());
|
||||
}
|
||||
{
|
||||
assoc_type testset(values.begin(), values.end());
|
||||
testset.rebalance();
|
||||
iterator_t it = original_testset.begin();
|
||||
TEST_INTRUSIVE_SEQUENCE_EXPECTED(original_testset, testset.begin());
|
||||
}
|
||||
|
||||
|
450
test/has_member_function_callable_with.cpp
Normal file
450
test/has_member_function_callable_with.cpp
Normal file
@@ -0,0 +1,450 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2011-2011. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/detail/workaround.hpp>
|
||||
#include <cstddef>
|
||||
#include <boost/move/move.hpp>
|
||||
|
||||
namespace boost{
|
||||
namespace intrusive{
|
||||
namespace intrusive_detail{
|
||||
namespace has_member_function_callable_with {
|
||||
|
||||
struct dont_care
|
||||
{
|
||||
dont_care(...);
|
||||
};
|
||||
|
||||
struct private_type
|
||||
{
|
||||
static private_type p;
|
||||
private_type const &operator,(int) const;
|
||||
};
|
||||
|
||||
typedef char yes_type;
|
||||
struct no_type{ char dummy[2]; };
|
||||
|
||||
template<typename T>
|
||||
no_type is_private_type(T const &);
|
||||
yes_type is_private_type(private_type const &);
|
||||
|
||||
}}}}
|
||||
|
||||
|
||||
namespace boost{
|
||||
namespace intrusive{
|
||||
namespace intrusive_detail{
|
||||
|
||||
template <typename Type>
|
||||
class has_member_function_named_func
|
||||
{
|
||||
struct BaseMixin
|
||||
{
|
||||
void func();
|
||||
};
|
||||
|
||||
struct Base : public Type, public BaseMixin {};
|
||||
template <typename T, T t> class Helper{};
|
||||
|
||||
template <typename U>
|
||||
static has_member_function_callable_with::no_type deduce
|
||||
(U*, Helper<void (BaseMixin::*)(), &U::func>* = 0);
|
||||
static has_member_function_callable_with::yes_type deduce(...);
|
||||
|
||||
public:
|
||||
static const bool value =
|
||||
sizeof(has_member_function_callable_with::yes_type) == sizeof(deduce((Base*)(0)));
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#if !defined(BOOST_CONTAINER_PERFECT_FORWARDING)
|
||||
|
||||
namespace boost{
|
||||
namespace intrusive{
|
||||
namespace intrusive_detail{
|
||||
|
||||
template<typename Fun, bool HasFunc
|
||||
, class P0 = void , class P1 = void , class P2 = void>
|
||||
struct has_member_function_callable_with_func_impl;
|
||||
|
||||
|
||||
template<typename Fun , class P0 , class P1 , class P2>
|
||||
struct has_member_function_callable_with_func_impl
|
||||
<Fun, false , P0 , P1 , P2>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
|
||||
}}}
|
||||
|
||||
|
||||
namespace boost{
|
||||
namespace intrusive{
|
||||
namespace intrusive_detail{
|
||||
|
||||
#if !defined(_MSC_VER) || (_MSC_VER != 1600)
|
||||
|
||||
template<class F, std::size_t N = sizeof(boost::move_detail::declval<F>().func(), 0)>
|
||||
struct zeroarg_checker_func
|
||||
{
|
||||
has_member_function_callable_with::yes_type dummy;
|
||||
zeroarg_checker_func(int);
|
||||
};
|
||||
|
||||
//For buggy compilers like MSVC 7.1, ((F*)0)->func() does not
|
||||
//fail but sizeof yields to 0.
|
||||
template<class F>
|
||||
struct zeroarg_checker_func<F, 0>
|
||||
{
|
||||
has_member_function_callable_with::no_type dummy;
|
||||
zeroarg_checker_func(int);
|
||||
};
|
||||
|
||||
template<typename Fun>
|
||||
struct has_member_function_callable_with_func_impl
|
||||
<Fun, true , void , void , void>
|
||||
{
|
||||
template<class U>
|
||||
static zeroarg_checker_func<U> Test(zeroarg_checker_func<U>*);
|
||||
|
||||
template <class U>
|
||||
static has_member_function_callable_with::no_type Test(...);
|
||||
|
||||
static const bool value = sizeof(Test< Fun >(0))
|
||||
== sizeof(has_member_function_callable_with::yes_type);
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template<typename Fun>
|
||||
struct has_member_function_callable_with_func_impl
|
||||
<Fun, true , void , void , void>
|
||||
{
|
||||
template<class U>
|
||||
static decltype(boost::move_detail::declval<Fun>().func(), has_member_function_callable_with::yes_type()) Test(Fun* f);
|
||||
|
||||
template<class U>
|
||||
static has_member_function_callable_with::no_type Test(...);
|
||||
static const bool value = sizeof(Test<Fun>((Fun*)0)) == sizeof(has_member_function_callable_with::yes_type);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
}}}
|
||||
|
||||
|
||||
namespace boost{
|
||||
namespace intrusive{
|
||||
namespace intrusive_detail{
|
||||
|
||||
|
||||
template<typename Fun>
|
||||
struct funwrap1_func : Fun
|
||||
{
|
||||
using Fun::func;
|
||||
has_member_function_callable_with::private_type
|
||||
func( has_member_function_callable_with::dont_care) const;
|
||||
};
|
||||
|
||||
template<typename Fun , class P0>
|
||||
struct has_member_function_callable_with_func_impl
|
||||
<Fun, true , P0 , void , void>
|
||||
{
|
||||
|
||||
typedef funwrap1_func<Fun> FunWrap;
|
||||
|
||||
static bool const value = (sizeof(has_member_function_callable_with::no_type) ==
|
||||
sizeof(has_member_function_callable_with::is_private_type
|
||||
( (::boost::move_detail::declval< FunWrap >().func( ::boost::move_detail::declval<P0>() ), 0) )
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
namespace boost{
|
||||
namespace intrusive{
|
||||
namespace intrusive_detail{
|
||||
|
||||
|
||||
template<typename Fun>
|
||||
struct funwrap2_func: Fun
|
||||
{
|
||||
using Fun::func;
|
||||
has_member_function_callable_with::private_type
|
||||
func( has_member_function_callable_with::dont_care , has_member_function_callable_with::dont_care) const;
|
||||
};
|
||||
|
||||
template<typename Fun , class P0 , class P1>
|
||||
struct has_member_function_callable_with_func_impl
|
||||
<Fun, true , P0 , P1 , void>
|
||||
{
|
||||
typedef funwrap2_func<Fun> FunWrap;
|
||||
|
||||
static bool const value = (sizeof(has_member_function_callable_with::no_type) ==
|
||||
sizeof(has_member_function_callable_with::is_private_type
|
||||
( (::boost::move_detail::declval< FunWrap >().
|
||||
func( ::boost::move_detail::declval<P0>()
|
||||
, ::boost::move_detail::declval<P1>() )
|
||||
, 0) )
|
||||
)
|
||||
);
|
||||
};
|
||||
}}}
|
||||
|
||||
namespace boost{
|
||||
namespace intrusive{
|
||||
namespace intrusive_detail{
|
||||
|
||||
|
||||
template<typename Fun>
|
||||
struct funwrap3_func: Fun
|
||||
{
|
||||
using Fun::func;
|
||||
has_member_function_callable_with::private_type
|
||||
func( has_member_function_callable_with::dont_care
|
||||
, has_member_function_callable_with::dont_care
|
||||
, has_member_function_callable_with::dont_care) const;
|
||||
};
|
||||
|
||||
template<typename Fun , class P0 , class P1 , class P2>
|
||||
struct has_member_function_callable_with_func_impl
|
||||
<Fun, true , P0 , P1 , P2 >
|
||||
{
|
||||
typedef funwrap3_func<Fun> FunWrap;
|
||||
|
||||
static bool const value = (sizeof(has_member_function_callable_with::no_type) ==
|
||||
sizeof(has_member_function_callable_with::is_private_type
|
||||
( (::boost::move_detail::declval< FunWrap >().
|
||||
func( ::boost::move_detail::declval<P0>()
|
||||
, ::boost::move_detail::declval<P1>()
|
||||
, ::boost::move_detail::declval<P2>() )
|
||||
, 0) )
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
template<typename Fun
|
||||
, class P0 = void , class P1 = void, typename P2 = void>
|
||||
struct has_member_function_callable_with_func
|
||||
: public has_member_function_callable_with_func_impl
|
||||
<Fun, has_member_function_named_func<Fun>::value, P0 , P1 , P2 >
|
||||
{};
|
||||
|
||||
}}}
|
||||
|
||||
#else
|
||||
|
||||
namespace boost{
|
||||
namespace intrusive{
|
||||
namespace intrusive_detail{
|
||||
|
||||
template<typename Fun, bool HasFunc, class ...Args>
|
||||
struct has_member_function_callable_with_func_impl;
|
||||
|
||||
template<typename Fun, class ...Args>
|
||||
struct has_member_function_callable_with_func_impl
|
||||
<Fun, false, Args...>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
|
||||
}}}
|
||||
|
||||
|
||||
namespace boost{
|
||||
namespace intrusive{
|
||||
namespace intrusive_detail{
|
||||
|
||||
template<class F, std::size_t N = sizeof(boost::move_detail::declval<F>().func(), 0)>
|
||||
struct zeroarg_checker_func
|
||||
{
|
||||
has_member_function_callable_with::yes_type dummy;
|
||||
zeroarg_checker_func(int);
|
||||
};
|
||||
|
||||
//For buggy compilers like MSVC 7.1, ((F*)0)->func() does not
|
||||
//fail but sizeof yields to 0.
|
||||
template<class F>
|
||||
struct zeroarg_checker_func<F, 0>
|
||||
{
|
||||
has_member_function_callable_with::no_type dummy;
|
||||
zeroarg_checker_func(int);
|
||||
};
|
||||
|
||||
template<typename Fun>
|
||||
struct has_member_function_callable_with_func_impl
|
||||
<Fun, true>
|
||||
{
|
||||
template<class U>
|
||||
static zeroarg_checker_func<U> Test(zeroarg_checker_func<U>*);
|
||||
|
||||
template <class U>
|
||||
static has_member_function_callable_with::no_type Test(...);
|
||||
|
||||
static const bool value = sizeof(Test< Fun >(0))
|
||||
== sizeof(has_member_function_callable_with::yes_type);
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
|
||||
namespace boost{
|
||||
namespace intrusive{
|
||||
namespace intrusive_detail{
|
||||
|
||||
|
||||
template<typename Fun, class ...DontCares>
|
||||
struct funwrap_func : Fun
|
||||
{
|
||||
using Fun::func;
|
||||
has_member_function_callable_with::private_type
|
||||
func(DontCares...) const;
|
||||
};
|
||||
|
||||
template<typename Fun, class ...Args>
|
||||
struct has_member_function_callable_with_func_impl
|
||||
<Fun, true , Args...>
|
||||
{
|
||||
template<class T>
|
||||
struct make_dontcare
|
||||
{
|
||||
typedef has_member_function_callable_with::dont_care type;
|
||||
};
|
||||
|
||||
typedef funwrap_func<Fun, typename make_dontcare<Args>::type...> FunWrap;
|
||||
|
||||
static bool const value = (sizeof(has_member_function_callable_with::no_type) ==
|
||||
sizeof(has_member_function_callable_with::is_private_type
|
||||
( (::boost::move_detail::declval< FunWrap >().func( ::boost::move_detail::declval<Args>()... ), 0) )
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
template<typename Fun, class ...Args>
|
||||
struct has_member_function_callable_with_func
|
||||
: public has_member_function_callable_with_func_impl
|
||||
<Fun, has_member_function_named_func<Fun>::value, Args... >
|
||||
{};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
struct functor
|
||||
{
|
||||
void func();
|
||||
void func(const int&);
|
||||
void func(const int&, const int&);
|
||||
void func(const int&, const int&, const int&);
|
||||
};
|
||||
|
||||
struct functor2
|
||||
{
|
||||
void func(char*);
|
||||
void func(int, char*);
|
||||
void func(int, char*, double);
|
||||
void func(const int&, char*, void *);
|
||||
};
|
||||
|
||||
struct functor3
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
struct functor4
|
||||
{
|
||||
void func(...);
|
||||
template<class T>
|
||||
void func(int, const T &);
|
||||
|
||||
template<class T>
|
||||
void func(const T &);
|
||||
|
||||
template<class T, class U>
|
||||
void func(int, const T &, const U &);
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost::intrusive::intrusive_detail;
|
||||
|
||||
{
|
||||
int check1[ has_member_function_callable_with_func<functor>::value ? 1 : -1];
|
||||
int check2[!has_member_function_callable_with_func<functor2>::value ? 1 : -1];
|
||||
int check3[!has_member_function_callable_with_func<functor3>::value ? 1 : -1];
|
||||
int check4[ has_member_function_callable_with_func<functor4>::value ? 1 : -1];
|
||||
(void)check1;
|
||||
(void)check2;
|
||||
(void)check3;
|
||||
(void)check4;
|
||||
}
|
||||
|
||||
{
|
||||
int check1[ has_member_function_callable_with_func<functor, int>::value ? 1 : -1];
|
||||
int check2[!has_member_function_callable_with_func<functor, char*>::value ? 1 : -1];
|
||||
int check3[!has_member_function_callable_with_func<functor2, int>::value ? 1 : -1];
|
||||
int check4[ has_member_function_callable_with_func<functor2, char*>::value ? 1 : -1];
|
||||
int check5[!has_member_function_callable_with_func<functor3, int>::value ? 1 : -1];
|
||||
int check6[!has_member_function_callable_with_func<functor3, char*>::value ? 1 : -1];
|
||||
int check7[ has_member_function_callable_with_func<functor4, int>::value ? 1 : -1];
|
||||
int check8[ has_member_function_callable_with_func<functor4, char*>::value ? 1 : -1];
|
||||
(void)check1;
|
||||
(void)check2;
|
||||
(void)check3;
|
||||
(void)check4;
|
||||
(void)check5;
|
||||
(void)check6;
|
||||
(void)check7;
|
||||
(void)check8;
|
||||
}
|
||||
|
||||
{
|
||||
int check1[ has_member_function_callable_with_func<functor, int, int>::value ? 1 : -1];
|
||||
int check2[!has_member_function_callable_with_func<functor, int, char*>::value ? 1 : -1];
|
||||
int check3[!has_member_function_callable_with_func<functor2, int, int>::value ? 1 : -1];
|
||||
int check4[ has_member_function_callable_with_func<functor2, int, char*>::value ? 1 : -1];
|
||||
int check5[!has_member_function_callable_with_func<functor3, int, int>::value ? 1 : -1];
|
||||
int check6[!has_member_function_callable_with_func<functor3, int, char*>::value ? 1 : -1];
|
||||
int check7[ has_member_function_callable_with_func<functor4, int, char*>::value ? 1 : -1];
|
||||
(void)check1;
|
||||
(void)check2;
|
||||
(void)check3;
|
||||
(void)check4;
|
||||
(void)check5;
|
||||
(void)check6;
|
||||
(void)check7;
|
||||
}
|
||||
|
||||
{
|
||||
int check1[ has_member_function_callable_with_func<functor, int, int, int>::value ? 1 : -1];
|
||||
int check2[!has_member_function_callable_with_func<functor, int, char*, int>::value ? 1 : -1];
|
||||
int check3[!has_member_function_callable_with_func<functor2, int, int, int>::value ? 1 : -1];
|
||||
int check4[ has_member_function_callable_with_func<functor2, int, char*, void*>::value ? 1 : -1];
|
||||
int check5[!has_member_function_callable_with_func<functor3, int, int, int>::value ? 1 : -1];
|
||||
int check6[!has_member_function_callable_with_func<functor3, int, char*, void*>::value ? 1 : -1];
|
||||
int check7[ has_member_function_callable_with_func<functor4, int, char*, int>::value ? 1 : -1];
|
||||
(void)check1;
|
||||
(void)check2;
|
||||
(void)check3;
|
||||
(void)check4;
|
||||
(void)check5;
|
||||
(void)check6;
|
||||
(void)check7;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
@@ -12,7 +12,7 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
#include "itestvalue.hpp"
|
||||
#include "smart_ptr.hpp"
|
||||
#include "common_functors.hpp"
|
||||
@@ -221,7 +221,7 @@ void test_list<ValueTraits>
|
||||
|
||||
{
|
||||
typename list_type::const_iterator ci = typename list_type::iterator();
|
||||
//typename list_type::iterator i = typename list_type::const_iterator();
|
||||
(void)ci;
|
||||
}
|
||||
|
||||
testlist.insert (i, values[0]);
|
||||
@@ -495,6 +495,5 @@ int main( int, char* [] )
|
||||
test_main_template<smart_ptr<void>, false>()();
|
||||
test_main_template<void*, true>()();
|
||||
test_main_template<smart_ptr<void>, true>()();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#include <boost/intrusive/splay_set.hpp>
|
||||
#include <boost/intrusive/treap_set.hpp>
|
||||
#include <boost/intrusive/detail/mpl.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
#include "smart_ptr.hpp"
|
||||
#include <vector>
|
||||
|
||||
@@ -92,7 +93,8 @@ int main()
|
||||
List my_list;
|
||||
Slist my_slist;
|
||||
Set my_set;
|
||||
USet my_uset(USet::bucket_traits(buckets, 100));
|
||||
USet my_uset(USet::bucket_traits
|
||||
(pointer_traits<USet::bucket_ptr>::pointer_to(buckets[0]), 100));
|
||||
|
||||
AvlSet my_avlset;
|
||||
SplaySet my_splayset;
|
||||
|
201
test/pointer_traits_test.cpp
Normal file
201
test/pointer_traits_test.cpp
Normal file
@@ -0,0 +1,201 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2011-2011. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
|
||||
template<class T>
|
||||
class CompleteSmartPtr
|
||||
{
|
||||
template <class U>
|
||||
friend class CompleteSmartPtr;
|
||||
|
||||
public:
|
||||
|
||||
#if !defined(BOOST_NO_TEMPLATE_ALIASES)
|
||||
template <class U> using rebind = CompleteSmartPtr<U>;
|
||||
#else
|
||||
template <class U> struct rebind
|
||||
{ typedef CompleteSmartPtr<U> other; };
|
||||
#endif
|
||||
|
||||
typedef char difference_type;
|
||||
typedef T element_type;
|
||||
|
||||
CompleteSmartPtr()
|
||||
: ptr_(0)
|
||||
{}
|
||||
|
||||
explicit CompleteSmartPtr(T &p)
|
||||
: ptr_(&p)
|
||||
{}
|
||||
|
||||
CompleteSmartPtr(const CompleteSmartPtr &c)
|
||||
{ this->ptr_ = c.ptr_; }
|
||||
|
||||
CompleteSmartPtr & operator=(const CompleteSmartPtr &c)
|
||||
{ this->ptr_ = c.ptr_; }
|
||||
|
||||
static CompleteSmartPtr pointer_to(T &r)
|
||||
{ return CompleteSmartPtr(r); }
|
||||
|
||||
T * operator->() const
|
||||
{ return ptr_; }
|
||||
|
||||
T & operator *() const
|
||||
{ return *ptr_; }
|
||||
|
||||
template<class U>
|
||||
static CompleteSmartPtr static_cast_from(const CompleteSmartPtr<U> &uptr)
|
||||
{ return CompleteSmartPtr(*static_cast<element_type*>(uptr.ptr_)); }
|
||||
|
||||
template<class U>
|
||||
static CompleteSmartPtr const_cast_from(const CompleteSmartPtr<U> &uptr)
|
||||
{ return CompleteSmartPtr(*const_cast<element_type*>(uptr.ptr_)); }
|
||||
|
||||
template<class U>
|
||||
static CompleteSmartPtr dynamic_cast_from(const CompleteSmartPtr<U> &uptr)
|
||||
{ return CompleteSmartPtr(*dynamic_cast<element_type*>(uptr.ptr_)); }
|
||||
|
||||
friend bool operator ==(const CompleteSmartPtr &l, const CompleteSmartPtr &r)
|
||||
{ return l.ptr_ == r.ptr_; }
|
||||
|
||||
friend bool operator !=(const CompleteSmartPtr &l, const CompleteSmartPtr &r)
|
||||
{ return l.ptr_ != r.ptr_; }
|
||||
|
||||
private:
|
||||
T *ptr_;
|
||||
};
|
||||
|
||||
|
||||
template<class T>
|
||||
class SimpleSmartPtr
|
||||
{
|
||||
public:
|
||||
|
||||
SimpleSmartPtr()
|
||||
: ptr_(0)
|
||||
{}
|
||||
|
||||
explicit SimpleSmartPtr(T *p)
|
||||
: ptr_(p)
|
||||
{}
|
||||
|
||||
SimpleSmartPtr(const SimpleSmartPtr &c)
|
||||
{ this->ptr_ = c.ptr_; }
|
||||
|
||||
SimpleSmartPtr & operator=(const SimpleSmartPtr &c)
|
||||
{ this->ptr_ = c.ptr_; }
|
||||
|
||||
friend bool operator ==(const SimpleSmartPtr &l, const SimpleSmartPtr &r)
|
||||
{ return l.ptr_ == r.ptr_; }
|
||||
|
||||
friend bool operator !=(const SimpleSmartPtr &l, const SimpleSmartPtr &r)
|
||||
{ return l.ptr_ != r.ptr_; }
|
||||
|
||||
T* operator->() const
|
||||
{ return ptr_; }
|
||||
|
||||
T & operator *() const
|
||||
{ return *ptr_; }
|
||||
|
||||
private:
|
||||
T *ptr_;
|
||||
};
|
||||
|
||||
class B{ public: virtual ~B(){} };
|
||||
class D : public B {};
|
||||
class DD : public virtual B {};
|
||||
|
||||
int main()
|
||||
{
|
||||
int dummy;
|
||||
|
||||
//Raw pointer
|
||||
BOOST_STATIC_ASSERT(( boost::is_same<boost::intrusive::pointer_traits
|
||||
<int*>::element_type, int>::value ));
|
||||
BOOST_STATIC_ASSERT(( boost::is_same<boost::intrusive::pointer_traits
|
||||
<int*>::pointer, int*>::value ));
|
||||
BOOST_STATIC_ASSERT(( boost::is_same<boost::intrusive::pointer_traits
|
||||
<int*>::difference_type, std::ptrdiff_t>::value ));
|
||||
BOOST_STATIC_ASSERT(( boost::is_same<boost::intrusive::pointer_traits
|
||||
<int*>::rebind_pointer<double>::type
|
||||
, double*>::value ));
|
||||
if(boost::intrusive::pointer_traits<int*>::pointer_to(dummy) != &dummy){
|
||||
return 1;
|
||||
}
|
||||
if(boost::intrusive::pointer_traits<D*>::static_cast_from((B*)0)){
|
||||
return 1;
|
||||
}
|
||||
if(boost::intrusive::pointer_traits<D*>::const_cast_from((const D*)0)){
|
||||
return 1;
|
||||
}
|
||||
if(boost::intrusive::pointer_traits<DD*>::dynamic_cast_from((B*)0)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
//Complete smart pointer
|
||||
BOOST_STATIC_ASSERT(( boost::is_same<boost::intrusive::pointer_traits
|
||||
< CompleteSmartPtr<int> >::element_type, int>::value ));
|
||||
BOOST_STATIC_ASSERT(( boost::is_same<boost::intrusive::pointer_traits
|
||||
< CompleteSmartPtr<int> >::pointer, CompleteSmartPtr<int> >::value ));
|
||||
BOOST_STATIC_ASSERT(( boost::is_same<boost::intrusive::pointer_traits
|
||||
< CompleteSmartPtr<int> >::difference_type, char>::value ));
|
||||
BOOST_STATIC_ASSERT(( boost::is_same<boost::intrusive::pointer_traits
|
||||
< CompleteSmartPtr<int> >::rebind_pointer<double>::type
|
||||
, CompleteSmartPtr<double> >::value ));
|
||||
if(boost::intrusive::pointer_traits< CompleteSmartPtr<int> >
|
||||
::pointer_to(dummy) != CompleteSmartPtr<int>(dummy)){
|
||||
return 1;
|
||||
}
|
||||
if(boost::intrusive::pointer_traits< CompleteSmartPtr<D> >::
|
||||
static_cast_from(CompleteSmartPtr<B>()) != CompleteSmartPtr<D>()){
|
||||
return 1;
|
||||
}
|
||||
if(boost::intrusive::pointer_traits< CompleteSmartPtr<D> >::
|
||||
const_cast_from(CompleteSmartPtr<const D>()) != CompleteSmartPtr<D>()){
|
||||
return 1;
|
||||
}
|
||||
if(boost::intrusive::pointer_traits< CompleteSmartPtr<DD> >::
|
||||
dynamic_cast_from(CompleteSmartPtr<B>()) != CompleteSmartPtr<DD>()){
|
||||
return 1;
|
||||
}
|
||||
|
||||
//Simple smart pointer
|
||||
BOOST_STATIC_ASSERT(( boost::is_same<boost::intrusive::pointer_traits
|
||||
< SimpleSmartPtr<int> >::element_type, int>::value ));
|
||||
BOOST_STATIC_ASSERT(( boost::is_same<boost::intrusive::pointer_traits
|
||||
< SimpleSmartPtr<int> >::pointer, SimpleSmartPtr<int> >::value ));
|
||||
BOOST_STATIC_ASSERT(( boost::is_same<boost::intrusive::pointer_traits
|
||||
< SimpleSmartPtr<int> >::difference_type, std::ptrdiff_t>::value ));
|
||||
BOOST_STATIC_ASSERT(( boost::is_same<boost::intrusive::pointer_traits
|
||||
< SimpleSmartPtr<int> >::rebind_pointer<double>::type
|
||||
, SimpleSmartPtr<double> >::value ));
|
||||
if(boost::intrusive::pointer_traits< SimpleSmartPtr<int> >
|
||||
::pointer_to(dummy) != SimpleSmartPtr<int>(&dummy)){
|
||||
return 1;
|
||||
}
|
||||
if(boost::intrusive::pointer_traits< SimpleSmartPtr<D> >::
|
||||
static_cast_from(SimpleSmartPtr<B>()) != SimpleSmartPtr<D>()){
|
||||
return 1;
|
||||
}
|
||||
if(boost::intrusive::pointer_traits< SimpleSmartPtr<D> >::
|
||||
const_cast_from(SimpleSmartPtr<const D>()) != SimpleSmartPtr<D>()){
|
||||
return 1;
|
||||
}
|
||||
if(boost::intrusive::pointer_traits< SimpleSmartPtr<DD> >::
|
||||
dynamic_cast_from(SimpleSmartPtr<B>()) != SimpleSmartPtr<DD>()){
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
@@ -13,7 +13,7 @@
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/slist.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
#include "itestvalue.hpp"
|
||||
#include "smart_ptr.hpp"
|
||||
#include "common_functors.hpp"
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#include <boost/iterator.hpp>
|
||||
#include <boost/intrusive/pointer_plus_bits.hpp>
|
||||
#include <boost/pointer_cast.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
@@ -108,6 +109,11 @@ class smart_ptr
|
||||
|
||||
public: //Public Functions
|
||||
|
||||
smart_ptr()
|
||||
: m_ptr(0)
|
||||
{}
|
||||
|
||||
/*
|
||||
//!Constructor from raw pointer (allows "0" pointer conversion). Never throws.
|
||||
explicit smart_ptr(pointer ptr = 0)
|
||||
: m_ptr(ptr)
|
||||
@@ -118,64 +124,67 @@ class smart_ptr
|
||||
smart_ptr(T *ptr)
|
||||
: m_ptr(ptr)
|
||||
{}
|
||||
|
||||
*/
|
||||
//!Constructor from other smart_ptr
|
||||
smart_ptr(const smart_ptr& ptr)
|
||||
: m_ptr(ptr.m_ptr)
|
||||
{}
|
||||
|
||||
static smart_ptr pointer_to(reference r)
|
||||
{ smart_ptr p; p.m_ptr = &r; return p; }
|
||||
|
||||
//!Constructor from other smart_ptr. If pointers of pointee types are
|
||||
//!convertible, offset_ptrs will be convertibles. Never throws.
|
||||
template<class T2>
|
||||
smart_ptr(const smart_ptr<T2> &ptr)
|
||||
: m_ptr(ptr.m_ptr)
|
||||
{}
|
||||
|
||||
/*
|
||||
//!Emulates static_cast operator. Never throws.
|
||||
template<class Y>
|
||||
smart_ptr(const smart_ptr<Y> & r, detail::static_cast_tag)
|
||||
: m_ptr(static_cast<PointedType*>(r.get()))
|
||||
: m_ptr(static_cast<PointedType*>(r.m_ptr))
|
||||
{}
|
||||
|
||||
//!Emulates const_cast operator. Never throws.
|
||||
template<class Y>
|
||||
smart_ptr(const smart_ptr<Y> & r, detail::const_cast_tag)
|
||||
: m_ptr(const_cast<PointedType*>(r.get()))
|
||||
: m_ptr(const_cast<PointedType*>(r.m_ptr))
|
||||
{}
|
||||
|
||||
//!Emulates dynamic_cast operator. Never throws.
|
||||
template<class Y>
|
||||
smart_ptr(const smart_ptr<Y> & r, detail::dynamic_cast_tag)
|
||||
: m_ptr(dynamic_cast<PointedType*>(r.get()))
|
||||
: m_ptr(dynamic_cast<PointedType*>(r.m_ptr))
|
||||
{}
|
||||
|
||||
//!Emulates reinterpret_cast operator. Never throws.
|
||||
template<class Y>
|
||||
smart_ptr(const smart_ptr<Y> & r, detail::reinterpret_cast_tag)
|
||||
: m_ptr(reinterpret_cast<PointedType*>(r.get()))
|
||||
: m_ptr(reinterpret_cast<PointedType*>(r.m_ptr))
|
||||
{}
|
||||
|
||||
//!Obtains raw pointer from offset. Never throws.
|
||||
pointer get() const
|
||||
{ return m_ptr; }
|
||||
|
||||
*/
|
||||
//!Pointer-like -> operator. It can return 0 pointer. Never throws.
|
||||
pointer operator->() const
|
||||
{ return this->get(); }
|
||||
{ return m_ptr; }
|
||||
|
||||
//!Dereferencing operator, if it is a null smart_ptr behavior
|
||||
//! is undefined. Never throws.
|
||||
reference operator* () const
|
||||
{ return *(this->get()); }
|
||||
{ return *m_ptr; }
|
||||
|
||||
//!Indexing operator. Never throws.
|
||||
reference operator[](std::ptrdiff_t idx) const
|
||||
{ return this->get()[idx]; }
|
||||
|
||||
{ return m_ptr[idx]; }
|
||||
/*
|
||||
//!Assignment from pointer (saves extra conversion). Never throws.
|
||||
smart_ptr& operator= (pointer from)
|
||||
{ m_ptr = from; return *this; }
|
||||
|
||||
*/
|
||||
//!Assignment from other smart_ptr. Never throws.
|
||||
smart_ptr& operator= (const smart_ptr & pt)
|
||||
{ m_ptr = pt.m_ptr; return *this; }
|
||||
@@ -188,11 +197,11 @@ class smart_ptr
|
||||
|
||||
//!smart_ptr + std::ptrdiff_t. Never throws.
|
||||
smart_ptr operator+ (std::ptrdiff_t offset) const
|
||||
{ return smart_ptr(this->get()+offset); }
|
||||
{ smart_ptr s; s.m_ptr = m_ptr + offset; return s; }
|
||||
|
||||
//!smart_ptr - std::ptrdiff_t. Never throws.
|
||||
smart_ptr operator- (std::ptrdiff_t offset) const
|
||||
{ return smart_ptr(this->get()-offset); }
|
||||
{ smart_ptr s; s.m_ptr = m_ptr - offset; return s; }
|
||||
|
||||
//!smart_ptr += std::ptrdiff_t. Never throws.
|
||||
smart_ptr &operator+= (std::ptrdiff_t offset)
|
||||
@@ -220,12 +229,12 @@ class smart_ptr
|
||||
|
||||
//!safe bool conversion operator. Never throws.
|
||||
operator unspecified_bool_type() const
|
||||
{ return this->get()? &self_t::unspecified_bool_type_func : 0; }
|
||||
{ return m_ptr? &self_t::unspecified_bool_type_func : 0; }
|
||||
|
||||
//!Not operator. Not needed in theory, but improves portability.
|
||||
//!Never throws.
|
||||
bool operator! () const
|
||||
{ return this->get() == 0; }
|
||||
{ return m_ptr == 0; }
|
||||
/*
|
||||
friend void swap (smart_ptr &pt, smart_ptr &pt2)
|
||||
{
|
||||
@@ -240,43 +249,43 @@ class smart_ptr
|
||||
template<class T1, class T2>
|
||||
inline bool operator== (const smart_ptr<T1> &pt1,
|
||||
const smart_ptr<T2> &pt2)
|
||||
{ return pt1.get() == pt2.get(); }
|
||||
{ return pt1.operator->() == pt2.operator->(); }
|
||||
|
||||
//!smart_ptr<T1> != smart_ptr<T2>. Never throws.
|
||||
template<class T1, class T2>
|
||||
inline bool operator!= (const smart_ptr<T1> &pt1,
|
||||
const smart_ptr<T2> &pt2)
|
||||
{ return pt1.get() != pt2.get(); }
|
||||
{ return pt1.operator->() != pt2.operator->(); }
|
||||
|
||||
//!smart_ptr<T1> < smart_ptr<T2>. Never throws.
|
||||
template<class T1, class T2>
|
||||
inline bool operator< (const smart_ptr<T1> &pt1,
|
||||
const smart_ptr<T2> &pt2)
|
||||
{ return pt1.get() < pt2.get(); }
|
||||
{ return pt1.operator->() < pt2.operator->(); }
|
||||
|
||||
//!smart_ptr<T1> <= smart_ptr<T2>. Never throws.
|
||||
template<class T1, class T2>
|
||||
inline bool operator<= (const smart_ptr<T1> &pt1,
|
||||
const smart_ptr<T2> &pt2)
|
||||
{ return pt1.get() <= pt2.get(); }
|
||||
{ return pt1.operator->() <= pt2.operator->(); }
|
||||
|
||||
//!smart_ptr<T1> > smart_ptr<T2>. Never throws.
|
||||
template<class T1, class T2>
|
||||
inline bool operator> (const smart_ptr<T1> &pt1,
|
||||
const smart_ptr<T2> &pt2)
|
||||
{ return pt1.get() > pt2.get(); }
|
||||
{ return pt1.operator->() > pt2.operator->(); }
|
||||
|
||||
//!smart_ptr<T1> >= smart_ptr<T2>. Never throws.
|
||||
template<class T1, class T2>
|
||||
inline bool operator>= (const smart_ptr<T1> &pt1,
|
||||
const smart_ptr<T2> &pt2)
|
||||
{ return pt1.get() >= pt2.get(); }
|
||||
{ return pt1.operator->() >= pt2.operator->(); }
|
||||
|
||||
//!operator<<
|
||||
template<class E, class T, class Y>
|
||||
inline std::basic_ostream<E, T> & operator<<
|
||||
(std::basic_ostream<E, T> & os, smart_ptr<Y> const & p)
|
||||
{ return os << p.get(); }
|
||||
{ return os << p.operator->(); }
|
||||
|
||||
//!operator>>
|
||||
template<class E, class T, class Y>
|
||||
@@ -292,24 +301,18 @@ inline smart_ptr<T> operator+(std::ptrdiff_t diff, const smart_ptr<T>& right)
|
||||
//!smart_ptr - smart_ptr
|
||||
template<class T, class T2>
|
||||
inline std::ptrdiff_t operator- (const smart_ptr<T> &pt, const smart_ptr<T2> &pt2)
|
||||
{ return pt.get()- pt2.get(); }
|
||||
{ return pt.operator->()- pt2.operator->(); }
|
||||
|
||||
//!swap specialization
|
||||
template<class T>
|
||||
inline void swap (smart_ptr<T> &pt,
|
||||
smart_ptr<T> &pt2)
|
||||
{
|
||||
typename smart_ptr<T>::value_type *ptr = pt.get();
|
||||
typename smart_ptr<T>::value_type *ptr = pt.operator->();
|
||||
pt = pt2;
|
||||
pt2 = ptr;
|
||||
}
|
||||
|
||||
//!detail::boost_intrusive_get_pointer() enables boost::mem_fn to recognize smart_ptr.
|
||||
//!Never throws.
|
||||
template<class T>
|
||||
inline T* boost_intrusive_get_pointer(const smart_ptr<T> & p)
|
||||
{ return p.get(); }
|
||||
|
||||
//!Simulation of static_cast between pointers. Never throws.
|
||||
template<class T, class U>
|
||||
inline smart_ptr<T>
|
||||
@@ -363,23 +366,26 @@ struct pointer_plus_bits<smart_ptr<T>, NumBits>
|
||||
typedef smart_ptr<T> pointer;
|
||||
|
||||
static pointer get_pointer(const pointer &n)
|
||||
{ return pointer_plus_bits<T*, NumBits>::get_pointer(n.get()); }
|
||||
{
|
||||
return pointer_traits<pointer>::pointer_to
|
||||
(*pointer_plus_bits<T*, NumBits>::get_pointer(n.operator->()));
|
||||
}
|
||||
|
||||
static void set_pointer(pointer &n, pointer p)
|
||||
{
|
||||
T *raw_n = n.get();
|
||||
pointer_plus_bits<T*, NumBits>::set_pointer(raw_n, p.get());
|
||||
n = raw_n;
|
||||
T *raw_n = n.operator->();
|
||||
pointer_plus_bits<T*, NumBits>::set_pointer(raw_n, p.operator->());
|
||||
n = pointer_traits<pointer>::pointer_to(*raw_n);
|
||||
}
|
||||
|
||||
static std::size_t get_bits(const pointer &n)
|
||||
{ return pointer_plus_bits<T*, NumBits>::get_bits(n.get()); }
|
||||
{ return pointer_plus_bits<T*, NumBits>::get_bits(n.operator->()); }
|
||||
|
||||
static void set_bits(pointer &n, std::size_t c)
|
||||
{
|
||||
T *raw_n = n.get();
|
||||
T *raw_n = n.operator->();
|
||||
pointer_plus_bits<T*, NumBits>::set_bits(raw_n, c);
|
||||
n = raw_n;
|
||||
n = pointer_traits<pointer>::pointer_to(*raw_n);
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -12,7 +12,7 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/splay_set.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
#include "itestvalue.hpp"
|
||||
#include "smart_ptr.hpp"
|
||||
#include "generic_multiset_test.hpp"
|
||||
|
@@ -14,7 +14,7 @@
|
||||
#include <boost/intrusive/set.hpp>
|
||||
#include <boost/intrusive/unordered_set.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
#include <vector>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
@@ -46,10 +46,11 @@ struct stateful_value_traits
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef typename node_traits::const_node_ptr const_node_ptr;
|
||||
typedef T value_type;
|
||||
typedef typename boost::pointer_to_other
|
||||
<node_ptr, T>::type pointer;
|
||||
typedef typename boost::pointer_to_other
|
||||
<node_ptr, const T>::type const_pointer;
|
||||
typedef typename pointer_traits<node_ptr>::
|
||||
template rebind_pointer<T>::type pointer;
|
||||
typedef typename pointer_traits<node_ptr>::
|
||||
template rebind_pointer<const T>::type const_pointer;
|
||||
|
||||
static const link_mode_type link_mode = normal_link;
|
||||
|
||||
stateful_value_traits(pointer values, node_ptr node_array)
|
||||
|
@@ -91,7 +91,6 @@ void test_sequence_container(Container & c, Data & d)
|
||||
c.insert( c.begin(), *i );
|
||||
c.insert( c.end(), *(++i) );
|
||||
}
|
||||
|
||||
BOOST_TEST( c.size() == 2 );
|
||||
BOOST_TEST( !c.empty() );
|
||||
|
||||
@@ -99,6 +98,17 @@ void test_sequence_container(Container & c, Data & d)
|
||||
i = c.erase( c.begin() );
|
||||
|
||||
BOOST_TEST( c.size() == 1 );
|
||||
BOOST_TEST( !c.empty() );
|
||||
|
||||
i = c.erase( c.begin() );
|
||||
|
||||
BOOST_TEST( c.size() == 0 );
|
||||
BOOST_TEST( c.empty() );
|
||||
|
||||
c.insert( c.begin(), *d.begin() );
|
||||
|
||||
BOOST_TEST( c.size() == 1 );
|
||||
BOOST_TEST( !c.empty() );
|
||||
|
||||
{
|
||||
typename Data::iterator i = d.begin();
|
||||
|
@@ -12,7 +12,7 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/unordered_set.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
#include "itestvalue.hpp"
|
||||
#include "smart_ptr.hpp"
|
||||
#include "common_functors.hpp"
|
||||
@@ -102,7 +102,9 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>:
|
||||
{
|
||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
||||
unordered_multiset_type testset(bucket_traits(buckets, BucketSize));
|
||||
unordered_multiset_type testset
|
||||
(bucket_traits(pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets[0]), BucketSize));
|
||||
testset.insert(values.begin(), values.end());
|
||||
test::test_container(testset);
|
||||
testset.clear();
|
||||
@@ -145,7 +147,9 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
|
||||
values[i].value_ = i;
|
||||
|
||||
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
||||
unordered_multiset_type testset(bucket_traits(buckets, BucketSize));
|
||||
unordered_multiset_type testset(bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets[0]), BucketSize));
|
||||
|
||||
for (int i = 0; i < 5; ++i)
|
||||
testset.insert (values[i]);
|
||||
@@ -175,7 +179,10 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
|
||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
||||
unordered_multiset_type testset1(values.begin(), values.end(), bucket_traits(buckets, BucketSize));
|
||||
unordered_multiset_type testset1
|
||||
(values.begin(), values.end(), bucket_traits
|
||||
(pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets[0]), BucketSize));
|
||||
|
||||
if(Incremental){
|
||||
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
|
||||
@@ -206,7 +213,9 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
|
||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||
typedef typename unordered_multiset_type::iterator iterator;
|
||||
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
||||
unordered_multiset_type testset(bucket_traits(buckets, BucketSize));
|
||||
unordered_multiset_type testset(bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets[0]), BucketSize));
|
||||
|
||||
testset.insert(&values[0] + 2, &values[0] + 5);
|
||||
|
||||
@@ -244,7 +253,9 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
|
||||
|
||||
//Now with a single bucket
|
||||
typename unordered_multiset_type::bucket_type single_bucket[1];
|
||||
unordered_multiset_type testset2(bucket_traits(single_bucket, 1));
|
||||
unordered_multiset_type testset2(bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(single_bucket[0]), 1));
|
||||
testset2.insert(&values[0], &values[0] + values.size());
|
||||
BOOST_TEST (testset2.erase(5) == 1);
|
||||
BOOST_TEST (testset2.erase(2) == 2);
|
||||
@@ -286,7 +297,9 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
|
||||
|
||||
//Now with a single bucket
|
||||
typename unordered_multiset_type::bucket_type single_bucket[1];
|
||||
unordered_multiset_type testset2(bucket_traits(single_bucket, 1));
|
||||
unordered_multiset_type testset2(bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(single_bucket[0]), 1));
|
||||
testset2.insert(&values[0], &values[0] + values.size());
|
||||
BOOST_TEST (testset2.erase(5) == 1);
|
||||
BOOST_TEST (testset2.erase(2) == 2);
|
||||
@@ -305,7 +318,9 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
|
||||
std::vector<typename ValueTraits::value_type> data (random_size);
|
||||
for (unsigned int j = 0; j < random_size; ++j)
|
||||
data[j].value_ = random_init[j];
|
||||
unordered_multiset_type testset_new(bucket_traits(single_bucket, 1));
|
||||
unordered_multiset_type testset_new(bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(single_bucket[0]), 1));
|
||||
testset_new.insert(&data[0], &data[0]+max);
|
||||
testset_new.erase(testset_new.iterator_to(data[i]));
|
||||
BOOST_TEST (testset_new.size() == (max -1));
|
||||
@@ -332,7 +347,8 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
|
||||
unordered_multiset_type testset
|
||||
( &random_init[0]
|
||||
, &random_init[0] + random_init.size()
|
||||
, bucket_traits(buckets, NumBucketSize));
|
||||
, bucket_traits(pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets[0]), NumBucketSize));
|
||||
|
||||
BOOST_TEST (testset.size() == random_init.size());
|
||||
|
||||
@@ -394,8 +410,12 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>:
|
||||
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
||||
|
||||
typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
|
||||
unordered_multiset_type testset1(&values[0], &values[0] + 2, bucket_traits(buckets, BucketSize));
|
||||
unordered_multiset_type testset2(bucket_traits(buckets2, BucketSize));
|
||||
unordered_multiset_type testset1(&values[0], &values[0] + 2,
|
||||
bucket_traits(pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets[0]), BucketSize));
|
||||
unordered_multiset_type testset2(bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets2[0]), BucketSize));
|
||||
|
||||
testset2.insert (&values[0] + 2, &values[0] + 6);
|
||||
testset1.swap (testset2);
|
||||
@@ -445,7 +465,9 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
|
||||
//Build a uset
|
||||
typename unordered_multiset_type::bucket_type buckets1 [BucketSize];
|
||||
typename unordered_multiset_type::bucket_type buckets2 [BucketSize*2];
|
||||
unordered_multiset_type testset1(&values[0], &values[0] + values.size(), bucket_traits(buckets1, BucketSize));
|
||||
unordered_multiset_type testset1(&values[0], &values[0] + values.size(),
|
||||
bucket_traits(pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), BucketSize));
|
||||
//Test current state
|
||||
BOOST_TEST(testset1.split_count() == BucketSize/2);
|
||||
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
|
||||
@@ -472,21 +494,27 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
|
||||
//Try incremental hashing specifying a new bucket traits pointing to the same array
|
||||
//
|
||||
//This incremental rehash should fail because the new size is not twice the original
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets1, BucketSize)) == false);
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), BucketSize)) == false);
|
||||
BOOST_TEST(testset1.split_count() == BucketSize);
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
//This incremental rehash should success because the new size is twice the original
|
||||
//and split_count is the same as the old bucket count
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets1, BucketSize*2)) == true);
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), BucketSize*2)) == true);
|
||||
BOOST_TEST(testset1.split_count() == BucketSize);
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
//This incremental rehash should also success because the new size is half the original
|
||||
//and split_count is the same as the new bucket count
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets1, BucketSize)) == true);
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), BucketSize)) == true);
|
||||
BOOST_TEST(testset1.split_count() == BucketSize);
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
@@ -495,39 +523,51 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
|
||||
//Try incremental hashing specifying a new bucket traits pointing to the same array
|
||||
//
|
||||
//This incremental rehash should fail because the new size is not twice the original
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets2, BucketSize)) == false);
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets2[0]), BucketSize)) == false);
|
||||
BOOST_TEST(testset1.split_count() == BucketSize);
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
//This incremental rehash should success because the new size is twice the original
|
||||
//and split_count is the same as the old bucket count
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets2, BucketSize*2)) == true);
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets2[0]), BucketSize*2)) == true);
|
||||
BOOST_TEST(testset1.split_count() == BucketSize);
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
//This incremental rehash should also success because the new size is half the original
|
||||
//and split_count is the same as the new bucket count
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets1, BucketSize)) == true);
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), BucketSize)) == true);
|
||||
BOOST_TEST(testset1.split_count() == BucketSize);
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
//Full shrink rehash
|
||||
testset1.rehash(bucket_traits(buckets1, 4));
|
||||
testset1.rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), 4));
|
||||
BOOST_TEST (testset1.size() == values.size());
|
||||
BOOST_TEST (testset1.incremental_rehash() == false);
|
||||
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
//Full shrink rehash again
|
||||
testset1.rehash(bucket_traits(buckets1, 2));
|
||||
testset1.rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), 2));
|
||||
BOOST_TEST (testset1.size() == values.size());
|
||||
BOOST_TEST (testset1.incremental_rehash() == false);
|
||||
{ int init_values [] = { 2, 2, 4, 3, 5, 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
//Full growing rehash
|
||||
testset1.rehash(bucket_traits(buckets1, BucketSize));
|
||||
testset1.rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), BucketSize));
|
||||
BOOST_TEST (testset1.size() == values.size());
|
||||
BOOST_TEST (testset1.incremental_rehash() == false);
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
@@ -575,29 +615,39 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
|
||||
typename unordered_multiset_type::bucket_type buckets2 [2];
|
||||
typename unordered_multiset_type::bucket_type buckets3 [BucketSize*2];
|
||||
|
||||
unordered_multiset_type testset1(&values[0], &values[0] + 6, bucket_traits(buckets1, BucketSize));
|
||||
unordered_multiset_type testset1(&values[0], &values[0] + 6, bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), BucketSize));
|
||||
BOOST_TEST (testset1.size() == values.size());
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
testset1.rehash(bucket_traits(buckets2, 2));
|
||||
testset1.rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets2[0]), 2));
|
||||
BOOST_TEST (testset1.size() == values.size());
|
||||
{ int init_values [] = { 4, 2, 2, 5, 3, 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
testset1.rehash(bucket_traits(buckets3, BucketSize*2));
|
||||
testset1.rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets3[0]), BucketSize*2));
|
||||
BOOST_TEST (testset1.size() == values.size());
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
//Now rehash reducing the buckets
|
||||
testset1.rehash(bucket_traits(buckets3, 2));
|
||||
testset1.rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets3[0]), 2));
|
||||
BOOST_TEST (testset1.size() == values.size());
|
||||
{ int init_values [] = { 4, 2, 2, 5, 3, 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
//Now rehash increasing the buckets
|
||||
testset1.rehash(bucket_traits(buckets3, BucketSize*2));
|
||||
testset1.rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets3[0]), BucketSize*2));
|
||||
BOOST_TEST (testset1.size() == values.size());
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
@@ -620,7 +670,9 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>:
|
||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_multiset_type::bucket_type buckets[BucketSize];
|
||||
unordered_multiset_type testset(values.begin(), values.end(), bucket_traits(buckets, BucketSize));
|
||||
unordered_multiset_type testset(values.begin(), values.end(), bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets[0]), BucketSize));
|
||||
|
||||
typedef typename unordered_multiset_type::iterator iterator;
|
||||
|
||||
@@ -658,8 +710,12 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
|
||||
//Test with equal bucket arrays
|
||||
typename unordered_multiset_type::bucket_type buckets1 [BucketSize];
|
||||
typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
|
||||
unordered_multiset_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize));
|
||||
unordered_multiset_type testset2 (bucket_traits(buckets2, BucketSize));
|
||||
unordered_multiset_type testset1 (values.begin(), values.end(), bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), BucketSize));
|
||||
unordered_multiset_type testset2 (bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets2[0]), BucketSize));
|
||||
|
||||
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||
//Ordering is not guarantee in the cloning so insert data in a set and test
|
||||
@@ -675,8 +731,12 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
|
||||
//Test with bigger source bucket arrays
|
||||
typename unordered_multiset_type::bucket_type buckets1 [BucketSize*2];
|
||||
typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
|
||||
unordered_multiset_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize*2));
|
||||
unordered_multiset_type testset2 (bucket_traits(buckets2, BucketSize));
|
||||
unordered_multiset_type testset1 (values.begin(), values.end(), bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), BucketSize*2));
|
||||
unordered_multiset_type testset2 (bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets2[0]), BucketSize));
|
||||
|
||||
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||
//Ordering is not guarantee in the cloning so insert data in a set and test
|
||||
@@ -692,8 +752,12 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
|
||||
//Test with smaller source bucket arrays
|
||||
typename unordered_multiset_type::bucket_type buckets1 [BucketSize];
|
||||
typename unordered_multiset_type::bucket_type buckets2 [BucketSize*2];
|
||||
unordered_multiset_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize));
|
||||
unordered_multiset_type testset2 (bucket_traits(buckets2, BucketSize*2));
|
||||
unordered_multiset_type testset1 (values.begin(), values.end(), bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), BucketSize));
|
||||
unordered_multiset_type testset2 (bucket_traits(
|
||||
pointer_traits<typename unordered_multiset_type::bucket_ptr>::
|
||||
pointer_to(buckets2[0]), BucketSize*2));
|
||||
|
||||
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||
//Ordering is not guaranteed in the cloning so insert data in a set and test
|
||||
|
@@ -12,7 +12,7 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/unordered_set.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
#include "itestvalue.hpp"
|
||||
#include "smart_ptr.hpp"
|
||||
#include "common_functors.hpp"
|
||||
@@ -101,7 +101,9 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::
|
||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||
{
|
||||
typename unordered_set_type::bucket_type buckets [BucketSize];
|
||||
unordered_set_type testset(bucket_traits(buckets, BucketSize));
|
||||
unordered_set_type testset(bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets[0]), BucketSize));
|
||||
testset.insert(values.begin(), values.end());
|
||||
test::test_container(testset);
|
||||
testset.clear();
|
||||
@@ -143,7 +145,9 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::test
|
||||
values[i].value_ = i;
|
||||
|
||||
typename unordered_set_type::bucket_type buckets [BucketSize];
|
||||
unordered_set_type testset(bucket_traits(buckets, BucketSize));
|
||||
unordered_set_type testset(bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets[0]), BucketSize));
|
||||
for (int i = 0; i < 5; ++i)
|
||||
testset.insert (values[i]);
|
||||
|
||||
@@ -171,7 +175,9 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::
|
||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_set_type::bucket_type buckets [BucketSize];
|
||||
unordered_set_type testset1(values.begin(), values.end(), bucket_traits(buckets, BucketSize));
|
||||
unordered_set_type testset1(values.begin(), values.end(), bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets[0]), BucketSize));
|
||||
BOOST_TEST (5 == std::distance(testset1.begin(), testset1.end()));
|
||||
|
||||
if(Incremental){
|
||||
@@ -204,7 +210,9 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::
|
||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_set_type::bucket_type buckets [BucketSize];
|
||||
unordered_set_type testset(bucket_traits(buckets, BucketSize));
|
||||
unordered_set_type testset(bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets[0]), BucketSize));
|
||||
testset.insert(&values[0] + 2, &values[0] + 5);
|
||||
|
||||
const unordered_set_type& const_testset = testset;
|
||||
@@ -263,8 +271,12 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::
|
||||
|
||||
typename unordered_set_type::bucket_type buckets1 [BucketSize];
|
||||
typename unordered_set_type::bucket_type buckets2 [BucketSize];
|
||||
unordered_set_type testset1(&values[0], &values[0] + 2, bucket_traits(buckets1, BucketSize));
|
||||
unordered_set_type testset2(bucket_traits(buckets2, BucketSize));
|
||||
unordered_set_type testset1(&values[0], &values[0] + 2, bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), BucketSize));
|
||||
unordered_set_type testset2(bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets2[0]), BucketSize));
|
||||
|
||||
testset2.insert (&values[0] + 2, &values[0] + 6);
|
||||
testset1.swap (testset2);
|
||||
@@ -307,7 +319,9 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::
|
||||
//Build a uset
|
||||
typename unordered_set_type::bucket_type buckets1 [BucketSize];
|
||||
typename unordered_set_type::bucket_type buckets2 [BucketSize*2];
|
||||
unordered_set_type testset1(&values[0], &values[0] + 6, bucket_traits(buckets1, BucketSize));
|
||||
unordered_set_type testset1(&values[0], &values[0] + 6, bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), BucketSize));
|
||||
//Test current state
|
||||
BOOST_TEST(testset1.split_count() == BucketSize/2);
|
||||
{ int init_values [] = { 4, 5, 1, 2, 3 };
|
||||
@@ -334,21 +348,27 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::
|
||||
//Try incremental hashing specifying a new bucket traits pointing to the same array
|
||||
//
|
||||
//This incremental rehash should fail because the new size is not twice the original
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets1, BucketSize)) == false);
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), BucketSize)) == false);
|
||||
BOOST_TEST(testset1.split_count() == BucketSize);
|
||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
//This incremental rehash should success because the new size is twice the original
|
||||
//and split_count is the same as the old bucket count
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets1, BucketSize*2)) == true);
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), BucketSize*2)) == true);
|
||||
BOOST_TEST(testset1.split_count() == BucketSize);
|
||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
//This incremental rehash should also success because the new size is half the original
|
||||
//and split_count is the same as the new bucket count
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets1, BucketSize)) == true);
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), BucketSize)) == true);
|
||||
BOOST_TEST(testset1.split_count() == BucketSize);
|
||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
@@ -357,39 +377,51 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::
|
||||
//Try incremental hashing specifying a new bucket traits pointing to the same array
|
||||
//
|
||||
//This incremental rehash should fail because the new size is not twice the original
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets2, BucketSize)) == false);
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets2[0]), BucketSize)) == false);
|
||||
BOOST_TEST(testset1.split_count() == BucketSize);
|
||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
//This incremental rehash should success because the new size is twice the original
|
||||
//and split_count is the same as the old bucket count
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets2, BucketSize*2)) == true);
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets2[0]), BucketSize*2)) == true);
|
||||
BOOST_TEST(testset1.split_count() == BucketSize);
|
||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
//This incremental rehash should also success because the new size is half the original
|
||||
//and split_count is the same as the new bucket count
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets1, BucketSize)) == true);
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), BucketSize)) == true);
|
||||
BOOST_TEST(testset1.split_count() == BucketSize);
|
||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
//Full shrink rehash
|
||||
testset1.rehash(bucket_traits(buckets1, 4));
|
||||
testset1.rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), 4));
|
||||
BOOST_TEST (testset1.size() == values.size()-1);
|
||||
BOOST_TEST (testset1.incremental_rehash() == false);
|
||||
{ int init_values [] = { 4, 5, 1, 2, 3 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
//Full shrink rehash again
|
||||
testset1.rehash(bucket_traits(buckets1, 2));
|
||||
testset1.rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), 2));
|
||||
BOOST_TEST (testset1.size() == values.size()-1);
|
||||
BOOST_TEST (testset1.incremental_rehash() == false);
|
||||
{ int init_values [] = { 2, 4, 3, 5, 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
//Full growing rehash
|
||||
testset1.rehash(bucket_traits(buckets1, BucketSize));
|
||||
testset1.rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), BucketSize));
|
||||
BOOST_TEST (testset1.size() == values.size()-1);
|
||||
BOOST_TEST (testset1.incremental_rehash() == false);
|
||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||
@@ -439,29 +471,39 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::
|
||||
typename unordered_set_type::bucket_type buckets2 [2];
|
||||
typename unordered_set_type::bucket_type buckets3 [BucketSize*2];
|
||||
|
||||
unordered_set_type testset1(&values[0], &values[0] + 6, bucket_traits(buckets1, BucketSize));
|
||||
unordered_set_type testset1(&values[0], &values[0] + 6, bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), BucketSize));
|
||||
BOOST_TEST (testset1.size() == values.size()-1);
|
||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
testset1.rehash(bucket_traits(buckets2, 2));
|
||||
testset1.rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets2[0]), 2));
|
||||
BOOST_TEST (testset1.size() == values.size()-1);
|
||||
{ int init_values [] = { 4, 2, 5, 3, 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
testset1.rehash(bucket_traits(buckets3, BucketSize*2));
|
||||
testset1.rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets3[0]), BucketSize*2));
|
||||
BOOST_TEST (testset1.size() == values.size()-1);
|
||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
//Now rehash reducing the buckets
|
||||
testset1.rehash(bucket_traits(buckets3, 2));
|
||||
testset1.rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets3[0]), 2));
|
||||
BOOST_TEST (testset1.size() == values.size()-1);
|
||||
{ int init_values [] = { 4, 2, 5, 3, 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
//Now rehash increasing the buckets
|
||||
testset1.rehash(bucket_traits(buckets3, BucketSize*2));
|
||||
testset1.rehash(bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets3[0]), BucketSize*2));
|
||||
BOOST_TEST (testset1.size() == values.size()-1);
|
||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
@@ -485,7 +527,9 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::
|
||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_set_type::bucket_type buckets [BucketSize];
|
||||
unordered_set_type testset (values.begin(), values.end(), bucket_traits(buckets, BucketSize));
|
||||
unordered_set_type testset (values.begin(), values.end(), bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets[0]), BucketSize));
|
||||
typedef typename unordered_set_type::iterator iterator;
|
||||
|
||||
value_type cmp_val;
|
||||
@@ -521,8 +565,12 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>
|
||||
//Test with equal bucket arrays
|
||||
typename unordered_set_type::bucket_type buckets1 [BucketSize];
|
||||
typename unordered_set_type::bucket_type buckets2 [BucketSize];
|
||||
unordered_set_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize));
|
||||
unordered_set_type testset2 (bucket_traits(buckets2, BucketSize));
|
||||
unordered_set_type testset1 (values.begin(), values.end(), bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), BucketSize));
|
||||
unordered_set_type testset2 (bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets2[0]), BucketSize));
|
||||
|
||||
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||
//Ordering is not guarantee in the cloning so insert data in a set and test
|
||||
@@ -538,8 +586,12 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>
|
||||
//Test with bigger source bucket arrays
|
||||
typename unordered_set_type::bucket_type buckets1 [BucketSize*2];
|
||||
typename unordered_set_type::bucket_type buckets2 [BucketSize];
|
||||
unordered_set_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize*2));
|
||||
unordered_set_type testset2 (bucket_traits(buckets2, BucketSize));
|
||||
unordered_set_type testset1 (values.begin(), values.end(), bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), BucketSize*2));
|
||||
unordered_set_type testset2 (bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets2[0]), BucketSize));
|
||||
|
||||
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||
//Ordering is not guaranteed in the cloning so insert data in a set and test
|
||||
@@ -555,8 +607,12 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>
|
||||
//Test with smaller source bucket arrays
|
||||
typename unordered_set_type::bucket_type buckets1 [BucketSize];
|
||||
typename unordered_set_type::bucket_type buckets2 [BucketSize*2];
|
||||
unordered_set_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize));
|
||||
unordered_set_type testset2 (bucket_traits(buckets2, BucketSize*2));
|
||||
unordered_set_type testset1 (values.begin(), values.end(), bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets1[0]), BucketSize));
|
||||
unordered_set_type testset2 (bucket_traits(
|
||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||
pointer_to(buckets2[0]), BucketSize*2));
|
||||
|
||||
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||
//Ordering is not guarantee in the cloning so insert data in a set and test
|
||||
|
@@ -78,7 +78,8 @@ int main()
|
||||
|
||||
//Test the objects inserted in the base hook list
|
||||
for(; vect_it != vect_itend; ++vect_it, ++list_it)
|
||||
if(&*list_it != &*vect_it) return 1;
|
||||
if(&*list_it != &*vect_it)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
Reference in New Issue
Block a user