forked from boostorg/move
Added test for adl_move_swap.cpp
For move-emulation enabled types, if present, member swap is used, instead of the move-based swap.
This commit is contained in:
@@ -764,7 +764,8 @@ Many thanks to all boosters that have tested, reviewed and improved the library.
|
||||
|
||||
[section:release_notes_boost_1_58_00 Boost 1.58 Release]
|
||||
|
||||
* Added `BOOST_MOVE_BASE` utility.
|
||||
* Added [macroref BOOST_MOVE_BASE BOOST_MOVE_BASE] utility.
|
||||
* Added [funcref boost::adl_move_swap adl_move_swap] utility.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
@@ -43,45 +43,181 @@
|
||||
|
||||
#include <boost/move/utility_core.hpp> //for boost::move
|
||||
|
||||
#if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
|
||||
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
namespace boost_move_member_swap {
|
||||
|
||||
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 &);
|
||||
|
||||
template <typename Type>
|
||||
class has_member_function_named_swap
|
||||
{
|
||||
struct BaseMixin
|
||||
{
|
||||
void swap();
|
||||
};
|
||||
|
||||
struct Base : public Type, public BaseMixin { Base(); };
|
||||
template <typename T, T t> class Helper{};
|
||||
|
||||
template <typename U>
|
||||
static no_type deduce(U*, Helper<void (BaseMixin::*)(), &U::swap>* = 0);
|
||||
static yes_type deduce(...);
|
||||
|
||||
public:
|
||||
static const bool value = sizeof(yes_type) == sizeof(deduce((Base*)(0)));
|
||||
};
|
||||
|
||||
template<typename Fun, bool HasFunc>
|
||||
struct has_member_swap_impl
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<typename Fun>
|
||||
struct has_member_swap_impl<Fun, true>
|
||||
{
|
||||
struct FunWrap : Fun
|
||||
{
|
||||
FunWrap();
|
||||
|
||||
using Fun::swap;
|
||||
private_type swap(dont_care) const;
|
||||
};
|
||||
|
||||
static Fun &declval_fun();
|
||||
static FunWrap declval_wrap();
|
||||
|
||||
static bool const value =
|
||||
sizeof(no_type) == sizeof(is_private_type( (declval_wrap().swap(declval_fun()), 0)) );
|
||||
};
|
||||
|
||||
template<typename Fun>
|
||||
struct has_member_swap : public has_member_swap_impl
|
||||
<Fun, has_member_function_named_swap<Fun>::value>
|
||||
{};
|
||||
|
||||
} //namespace boost_move_member_swap
|
||||
|
||||
namespace boost_move_adl_swap{
|
||||
|
||||
template<class P1, class P2, bool = P1::value>
|
||||
struct and_op_impl
|
||||
{ static const bool value = false; };
|
||||
|
||||
template<class P1, class P2>
|
||||
struct and_op_impl<P1, P2, true>
|
||||
{ static const bool value = P2::value; };
|
||||
|
||||
template<class P1, class P2>
|
||||
struct and_op
|
||||
: and_op_impl<P1, P2>
|
||||
{};
|
||||
|
||||
//////
|
||||
|
||||
template<class P1, class P2, bool = P1::value>
|
||||
struct and_op_not_impl
|
||||
{ static const bool value = false; };
|
||||
|
||||
template<class P1, class P2>
|
||||
struct and_op_not_impl<P1, P2, true>
|
||||
{ static const bool value = !P2::value; };
|
||||
|
||||
template<class P1, class P2>
|
||||
struct and_op_not
|
||||
: and_op_not_impl<P1, P2>
|
||||
{};
|
||||
|
||||
template<class T>
|
||||
void swap_proxy(T& left, T& right, typename boost::move_detail::enable_if_c<!boost::move_detail::has_move_emulation_enabled_impl<T>::value>::type* = 0)
|
||||
void swap_proxy(T& x, T& y, typename boost::move_detail::enable_if_c<!boost::move_detail::has_move_emulation_enabled_impl<T>::value>::type* = 0)
|
||||
{
|
||||
//use std::swap if argument dependent lookup fails
|
||||
//Use using directive ("using namespace xxx;") instead as some older compilers
|
||||
//don't do ADL with using declarations ("using ns::func;").
|
||||
using namespace std;
|
||||
swap(left, right);
|
||||
swap(x, y);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void swap_proxy(T& left, T& right, typename boost::move_detail::enable_if_c<boost::move_detail::has_move_emulation_enabled_impl<T>::value>::type* = 0)
|
||||
void swap_proxy(T& x, T& y
|
||||
, typename boost::move_detail::enable_if< and_op_not_impl<boost::move_detail::has_move_emulation_enabled_impl<T>
|
||||
, boost_move_member_swap::has_member_swap<T> >
|
||||
>::type* = 0)
|
||||
{ T t(::boost::move(x)); x = ::boost::move(y); y = ::boost::move(t); }
|
||||
|
||||
template<class T>
|
||||
void swap_proxy(T& x, T& y
|
||||
, typename boost::move_detail::enable_if< and_op_impl< boost::move_detail::has_move_emulation_enabled_impl<T>
|
||||
, boost_move_member_swap::has_member_swap<T> >
|
||||
>::type* = 0)
|
||||
{ x.swap(y); }
|
||||
|
||||
} //namespace boost_move_adl_swap{
|
||||
|
||||
#else
|
||||
|
||||
namespace boost_move_adl_swap{
|
||||
|
||||
template<class T>
|
||||
void swap_proxy(T& x, T& y)
|
||||
{
|
||||
T tmp(::boost::move(left));
|
||||
left = ::boost::move(right);
|
||||
right = ::boost::move(tmp);
|
||||
using std::swap;
|
||||
swap(x, y);
|
||||
}
|
||||
|
||||
} //namespace boost_move_adl_swap{
|
||||
|
||||
#endif //#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
|
||||
namespace boost_move_adl_swap{
|
||||
|
||||
template<class T, std::size_t N>
|
||||
void swap_proxy(T (& left)[N], T (& right)[N])
|
||||
void swap_proxy(T (& x)[N], T (& y)[N])
|
||||
{
|
||||
for (std::size_t i = 0; i < N; ++i){
|
||||
::boost_move_adl_swap::swap_proxy(left[i], right[i]);
|
||||
::boost_move_adl_swap::swap_proxy(x[i], y[i]);
|
||||
}
|
||||
}
|
||||
|
||||
} //namespace boost_move_adl_swap {
|
||||
|
||||
#endif //!defined(BOOST_MOVE_DOXYGEN_INVOKED)
|
||||
|
||||
namespace boost{
|
||||
|
||||
// adl_move_swap has two template arguments, instead of one, to
|
||||
// avoid ambiguity when swapping objects of a Boost type that does
|
||||
// not have its own boost::swap overload.
|
||||
//! Exchanges the values of a and b, using Argument Dependent Lookup (ADL) to select a
|
||||
//! specialized swap function if available. If no specialized swap function is available,
|
||||
//! std::swap is used.
|
||||
//!
|
||||
//! <b>Exception</b>: If T uses Boost.Move's move emulation and the compiler has
|
||||
//! no rvalue references then:
|
||||
//!
|
||||
//! - If T has a <code>T::swap(T&)</code> member, that member is called.
|
||||
//! - Otherwise a move-based swap is called, equivalent to:
|
||||
//! <code>T t(::boost::move(x)); x = ::boost::move(y); y = ::boost::move(t);</code>.
|
||||
template<class T>
|
||||
void adl_move_swap(T& left, T& right)
|
||||
void adl_move_swap(T& x, T& y)
|
||||
{
|
||||
::boost_move_adl_swap::swap_proxy(left, right);
|
||||
::boost_move_adl_swap::swap_proxy(x, y);
|
||||
}
|
||||
|
||||
} //namespace boost{
|
||||
|
@@ -103,6 +103,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unique_ptr_types_test", "un
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "adl_move_swap", "adl_move_swap.vcproj", "{CD2617A8-79EB-6172-2CE4-26617AA3AC93}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
Debug = Debug
|
||||
@@ -215,6 +219,10 @@ Global
|
||||
{C57C28A3-4FE0-6208-BF87-B2B61D3A7675}.Debug.Build.0 = Debug|Win32
|
||||
{C57C28A3-4FE0-6208-BF87-B2B61D3A7675}.Release.ActiveCfg = Release|Win32
|
||||
{C57C28A3-4FE0-6208-BF87-B2B61D3A7675}.Release.Build.0 = Release|Win32
|
||||
{CD2617A8-79EB-6172-2CE4-26617AA3AC93}.Debug.ActiveCfg = Debug|Win32
|
||||
{CD2617A8-79EB-6172-2CE4-26617AA3AC93}.Debug.Build.0 = Debug|Win32
|
||||
{CD2617A8-79EB-6172-2CE4-26617AA3AC93}.Release.ActiveCfg = Release|Win32
|
||||
{CD2617A8-79EB-6172-2CE4-26617AA3AC93}.Release.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionItems) = postSolution
|
||||
..\..\..\..\boost\move\adl_move_swap.hpp = ..\..\..\..\boost\move\adl_move_swap.hpp
|
||||
|
134
proj/vc7ide/adl_move_swap.vcproj
Normal file
134
proj/vc7ide/adl_move_swap.vcproj
Normal file
@@ -0,0 +1,134 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="adl_move_swap"
|
||||
ProjectGUID="{CD2617A8-79EB-6172-2CE4-26617AA3AC93}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="../../Bin/Win32/Debug"
|
||||
IntermediateDirectory="Debug/move_adl_move_swap"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../../../.."
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
DisableLanguageExtensions="FALSE"
|
||||
TreatWChar_tAsBuiltInType="TRUE"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="winmm.lib"
|
||||
OutputFile="$(OutDir)/move_iterator_test_d.exe"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="../../../../stage/lib"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/move_adl_move_swap.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
FixedBaseAddress="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="../../Bin/Win32/Release"
|
||||
IntermediateDirectory="Release/move_adl_move_swap"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="../../../.."
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
|
||||
RuntimeLibrary="2"
|
||||
TreatWChar_tAsBuiltInType="TRUE"
|
||||
ForceConformanceInForLoopScope="FALSE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="winmm.lib"
|
||||
OutputFile="$(OutDir)/move_adl_move_swap.exe"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="../../../../stage/lib"
|
||||
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="{163D8753-4026-0A65-5C56-2BA532AD7FEF}">
|
||||
<File
|
||||
RelativePath="..\..\test\adl_move_swap.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
268
test/adl_move_swap.cpp
Normal file
268
test/adl_move_swap.cpp
Normal file
@@ -0,0 +1,268 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2014-2014.
|
||||
// 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/move for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/move/detail/config_begin.hpp>
|
||||
#include <boost/move/adl_move_swap.hpp>
|
||||
#include <boost/move/core.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
class swap_stats
|
||||
{
|
||||
public:
|
||||
static void reset_stats()
|
||||
{
|
||||
member_swap_calls = 0;
|
||||
friend_swap_calls = 0;
|
||||
move_cnstor_calls = 0;
|
||||
move_assign_calls = 0;
|
||||
copy_cnstor_calls = 0;
|
||||
copy_assign_calls = 0;
|
||||
}
|
||||
|
||||
static unsigned int member_swap_calls;
|
||||
static unsigned int friend_swap_calls;
|
||||
static unsigned int move_cnstor_calls;
|
||||
static unsigned int move_assign_calls;
|
||||
static unsigned int copy_cnstor_calls;
|
||||
static unsigned int copy_assign_calls;
|
||||
};
|
||||
|
||||
unsigned int swap_stats::member_swap_calls = 0;
|
||||
unsigned int swap_stats::friend_swap_calls = 0;
|
||||
unsigned int swap_stats::move_cnstor_calls = 0;
|
||||
unsigned int swap_stats::move_assign_calls = 0;
|
||||
unsigned int swap_stats::copy_cnstor_calls = 0;
|
||||
unsigned int swap_stats::copy_assign_calls = 0;
|
||||
|
||||
class movable : public swap_stats
|
||||
{
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(movable)
|
||||
public:
|
||||
movable() {}
|
||||
movable(BOOST_RV_REF(movable)) { ++move_cnstor_calls; }
|
||||
movable & operator=(BOOST_RV_REF(movable)){ ++move_assign_calls; return *this; }
|
||||
friend void swap(movable &, movable &) { ++friend_swap_calls; }
|
||||
};
|
||||
|
||||
class movable_swap_member : public swap_stats
|
||||
{
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(movable_swap_member)
|
||||
public:
|
||||
movable_swap_member() {}
|
||||
movable_swap_member(BOOST_RV_REF(movable_swap_member)) { ++move_cnstor_calls; }
|
||||
movable_swap_member & operator=(BOOST_RV_REF(movable_swap_member)){ ++move_assign_calls; return *this; }
|
||||
void swap(movable_swap_member &) { ++member_swap_calls; }
|
||||
friend void swap(movable_swap_member &, movable_swap_member &) { ++friend_swap_calls; }
|
||||
};
|
||||
|
||||
class copyable : public swap_stats
|
||||
{
|
||||
public:
|
||||
copyable() {}
|
||||
copyable(const copyable &) { ++copy_cnstor_calls; }
|
||||
copyable & operator=(const copyable&) { ++copy_assign_calls; return *this; }
|
||||
void swap(copyable &) { ++member_swap_calls; }
|
||||
friend void swap(copyable &, copyable &) { ++friend_swap_calls; }
|
||||
};
|
||||
|
||||
class no_swap : public swap_stats
|
||||
{
|
||||
private: unsigned m_state;
|
||||
public:
|
||||
explicit no_swap(unsigned i): m_state(i){}
|
||||
no_swap(const no_swap &x) { m_state = x.m_state; ++copy_cnstor_calls; }
|
||||
no_swap & operator=(const no_swap& x) { m_state = x.m_state; ++copy_assign_calls; return *this; }
|
||||
void swap(no_swap &) { ++member_swap_calls; }
|
||||
friend bool operator==(const no_swap &x, const no_swap &y) { return x.m_state == y.m_state; }
|
||||
friend bool operator!=(const no_swap &x, const no_swap &y) { return !(x==y); }
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
{ //movable
|
||||
movable x, y;
|
||||
swap_stats::reset_stats();
|
||||
::boost::adl_move_swap(x, y);
|
||||
#if defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
//In non rvalue reference compilers,
|
||||
//movable classes with no swap() member uses
|
||||
//boost::move() to implement swap.
|
||||
BOOST_TEST(swap_stats::friend_swap_calls == 0);
|
||||
BOOST_TEST(swap_stats::member_swap_calls == 0);
|
||||
BOOST_TEST(swap_stats::member_swap_calls == 0);
|
||||
BOOST_TEST(swap_stats::move_cnstor_calls == 1);
|
||||
BOOST_TEST(swap_stats::move_assign_calls == 2);
|
||||
BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
|
||||
BOOST_TEST(swap_stats::copy_assign_calls == 0);
|
||||
#else
|
||||
//In compilers with rvalue references, this should call friend swap via ADL
|
||||
BOOST_TEST(swap_stats::friend_swap_calls == 1);
|
||||
BOOST_TEST(swap_stats::member_swap_calls == 0);
|
||||
BOOST_TEST(swap_stats::member_swap_calls == 0);
|
||||
BOOST_TEST(swap_stats::move_cnstor_calls == 0);
|
||||
BOOST_TEST(swap_stats::move_assign_calls == 0);
|
||||
BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
|
||||
BOOST_TEST(swap_stats::copy_assign_calls == 0);
|
||||
#endif
|
||||
}
|
||||
{ //movable_swap_member
|
||||
movable_swap_member x, y;
|
||||
swap_stats::reset_stats();
|
||||
::boost::adl_move_swap(x, y);
|
||||
#if defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
//In non rvalue reference compilers,
|
||||
//movable classes with no swap() member uses
|
||||
//boost::move() to implement swap.
|
||||
BOOST_TEST(swap_stats::friend_swap_calls == 0);
|
||||
BOOST_TEST(swap_stats::member_swap_calls == 1);
|
||||
BOOST_TEST(swap_stats::move_cnstor_calls == 0);
|
||||
BOOST_TEST(swap_stats::move_assign_calls == 0);
|
||||
BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
|
||||
BOOST_TEST(swap_stats::copy_assign_calls == 0);
|
||||
#else
|
||||
//In compilers with rvalue references, this should call friend swap via ADL
|
||||
BOOST_TEST(swap_stats::friend_swap_calls == 1);
|
||||
BOOST_TEST(swap_stats::member_swap_calls == 0);
|
||||
BOOST_TEST(swap_stats::move_cnstor_calls == 0);
|
||||
BOOST_TEST(swap_stats::move_assign_calls == 0);
|
||||
BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
|
||||
BOOST_TEST(swap_stats::copy_assign_calls == 0);
|
||||
#endif
|
||||
}
|
||||
{ //copyable
|
||||
copyable x, y;
|
||||
swap_stats::reset_stats();
|
||||
::boost::adl_move_swap(x, y);
|
||||
//This should call friend swap via ADL
|
||||
BOOST_TEST(swap_stats::friend_swap_calls == 1);
|
||||
BOOST_TEST(swap_stats::member_swap_calls == 0);
|
||||
BOOST_TEST(swap_stats::move_cnstor_calls == 0);
|
||||
BOOST_TEST(swap_stats::move_assign_calls == 0);
|
||||
BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
|
||||
BOOST_TEST(swap_stats::copy_assign_calls == 0);
|
||||
}
|
||||
{ //no_swap
|
||||
no_swap x(1), y(2), x_back(x), y_back(y);
|
||||
swap_stats::reset_stats();
|
||||
::boost::adl_move_swap(x, y);
|
||||
//This should call std::swap which uses copies
|
||||
BOOST_TEST(swap_stats::friend_swap_calls == 0);
|
||||
BOOST_TEST(swap_stats::member_swap_calls == 0);
|
||||
BOOST_TEST(swap_stats::move_cnstor_calls == 0);
|
||||
BOOST_TEST(swap_stats::move_assign_calls == 0);
|
||||
BOOST_TEST(swap_stats::copy_cnstor_calls == 1);
|
||||
BOOST_TEST(swap_stats::copy_assign_calls == 2);
|
||||
BOOST_TEST(x == y_back);
|
||||
BOOST_TEST(y == x_back);
|
||||
BOOST_TEST(x != y);
|
||||
}
|
||||
return ::boost::report_errors();
|
||||
}
|
||||
#include <boost/move/detail/config_end.hpp>
|
||||
|
||||
/*
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
namespace boost_move_member_swap {
|
||||
|
||||
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 &);
|
||||
|
||||
template <typename Type>
|
||||
class has_member_function_named_swap
|
||||
{
|
||||
struct BaseMixin
|
||||
{
|
||||
void swap();
|
||||
};
|
||||
|
||||
struct Base : public Type, public BaseMixin { Base(); };
|
||||
template <typename T, T t> class Helper{};
|
||||
|
||||
template <typename U>
|
||||
static no_type deduce(U*, Helper<void (BaseMixin::*)(), &U::swap>* = 0);
|
||||
static yes_type deduce(...);
|
||||
|
||||
public:
|
||||
static const bool value = sizeof(yes_type) == sizeof(deduce((Base*)(0)));
|
||||
};
|
||||
|
||||
template<typename Fun, bool HasFunc>
|
||||
struct has_member_swap_impl
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<typename Fun>
|
||||
struct has_member_swap_impl<Fun, true>
|
||||
{
|
||||
struct FunWrap : Fun
|
||||
{
|
||||
FunWrap();
|
||||
|
||||
using Fun::swap;
|
||||
private_type swap(dont_care) const;
|
||||
};
|
||||
|
||||
static Fun &declval_fun();
|
||||
static FunWrap declval_wrap();
|
||||
|
||||
static bool const value =
|
||||
sizeof(no_type) == sizeof(is_private_type( (declval_wrap().swap(declval_fun()), 0)) );
|
||||
};
|
||||
|
||||
template<typename Fun>
|
||||
struct has_member_swap : public has_member_swap_impl
|
||||
<Fun, has_member_function_named_swap<Fun>::value>
|
||||
{};
|
||||
|
||||
} //namespace boost_move_member_swap
|
||||
|
||||
class noswap
|
||||
{
|
||||
public:
|
||||
void swap();
|
||||
};
|
||||
|
||||
class noneswap
|
||||
{
|
||||
};
|
||||
|
||||
class yesswap
|
||||
{
|
||||
public:
|
||||
void swap(yesswap&);
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_TEST(!boost_move_member_swap::has_member_swap<noswap>::value);
|
||||
BOOST_TEST(boost_move_member_swap::has_member_swap<yesswap>::value);
|
||||
BOOST_TEST(!boost_move_member_swap::has_member_swap<noneswap>::value);
|
||||
return boost::report_errors();
|
||||
}
|
||||
*/
|
Reference in New Issue
Block a user