Merge branch 'apolukhin-develop' into develop

This commit is contained in:
Ion Gaztañaga
2014-08-18 02:09:35 +02:00
10 changed files with 661 additions and 104 deletions

View File

@@ -757,16 +757,19 @@ Many thanks to all boosters that have tested, reviewed and improved the library.
[section:release_notes_boost_1_57_00 Boost 1.57 Release] [section:release_notes_boost_1_57_00 Boost 1.57 Release]
* Fixed bug [@https://svn.boost.org/trac/boost/ticket/9785 Trac #9785: ['"Compiler warning with intel icc in boost/move/core.hpp"]], * Added `move_if_noexcept` utility. Thanks to Antony Polukhin for the implementation.
* Fixed bugs:
* [@https://svn.boost.org/trac/boost/ticket/9785 Trac #9785: ['"Compiler warning with intel icc in boost/move/core.hpp"]],
[endsect] [endsect]
[section:release_notes_boost_1_56_00 Boost 1.56 Release] [section:release_notes_boost_1_56_00 Boost 1.56 Release]
* Added [macroref BOOST_MOVE_RET BOOST_MOVE_RET]. * Added [macroref BOOST_MOVE_RET BOOST_MOVE_RET].
* Fixed bug [@https://svn.boost.org/trac/boost/ticket/9482 #9482: ['"MSVC macros not undefined in boost/move/detail/config_end.hpp"]], * Fixed bugs:
[@https://svn.boost.org/trac/boost/ticket/9045 #9045: ['"Wrong macro name on docs"]], * [@https://svn.boost.org/trac/boost/ticket/9482 #9482: ['"MSVC macros not undefined in boost/move/detail/config_end.hpp"]],
[@https://svn.boost.org/trac/boost/ticket/8420 #8420: ['"move's is_convertible does not compile with aligned data"]]. * [@https://svn.boost.org/trac/boost/ticket/9045 #9045: ['"Wrong macro name on docs"]],
* [@https://svn.boost.org/trac/boost/ticket/8420 #8420: ['"move's is_convertible does not compile with aligned data"]].
[endsect] [endsect]

View File

@@ -9,7 +9,7 @@
// //
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
//! \file core.hpp //! \file
//! This header implements macros to define movable classes and //! This header implements macros to define movable classes and
//! move-aware functions //! move-aware functions
@@ -20,7 +20,7 @@
//boost_move_no_copy_constructor_or_assign typedef //boost_move_no_copy_constructor_or_assign typedef
//used to detect noncopyable types for other Boost libraries. //used to detect noncopyable types for other Boost libraries.
#ifdef BOOST_NO_CXX11_DELETED_FUNCTIONS #if defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
#define BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE) \ #define BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE) \
private:\ private:\
TYPE(TYPE &);\ TYPE(TYPE &);\

View File

@@ -133,6 +133,7 @@ struct remove_reference<T&>
typedef T type; typedef T type;
}; };
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template<class T> template<class T>
@@ -143,6 +144,30 @@ struct remove_reference<T&&>
#endif #endif
//add_const
template<class T>
struct add_const
{
typedef const T type;
};
template<class T>
struct add_const<T&>
{
typedef T& type;
};
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template<class T>
struct add_const<T&&>
{
typedef T&& type;
};
#endif
template<class T> template<class T>
struct is_class_or_union struct is_class_or_union
{ {

View File

@@ -10,7 +10,7 @@
// //
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
//! \file move.hpp //! \file
//! A general library header that includes //! A general library header that includes
//! the rest of top-level headers. //! the rest of top-level headers.

View File

@@ -18,6 +18,7 @@
#include <boost/type_traits/has_trivial_destructor.hpp> #include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/type_traits/is_nothrow_move_constructible.hpp> #include <boost/type_traits/is_nothrow_move_constructible.hpp>
#include <boost/type_traits/is_nothrow_move_assignable.hpp> #include <boost/type_traits/is_nothrow_move_assignable.hpp>
#include <boost/type_traits/is_copy_constructible.hpp>
#include <boost/move/detail/meta_utils.hpp> #include <boost/move/detail/meta_utils.hpp>
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
@@ -55,6 +56,18 @@ struct has_nothrow_move
namespace move_detail { namespace move_detail {
template <class T>
struct is_nothrow_move_constructible_or_uncopyable
: public ::boost::move_detail::integral_constant
< bool
//The standard requires is_nothrow_move_constructible for move_if_noexcept
//but a user (usually in C++03) might specialize has_nothrow_move which includes it
, boost::is_nothrow_move_constructible<T>::value ||
has_nothrow_move<T>::value ||
!boost::is_copy_constructible<T>::value
>
{};
// Code from Jeffrey Lee Hellrung, many thanks // Code from Jeffrey Lee Hellrung, many thanks
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES

View File

@@ -10,73 +10,74 @@
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
//! \file //! \file
//! This header includes core utilities from <tt><boost/move/utility_core.hpp></tt> and defines
//! some more advanced utilities such as:
#ifndef BOOST_MOVE_MOVE_UTILITY_HPP #ifndef BOOST_MOVE_MOVE_UTILITY_HPP
#define BOOST_MOVE_MOVE_UTILITY_HPP #define BOOST_MOVE_MOVE_UTILITY_HPP
#include <boost/move/detail/config_begin.hpp> #include <boost/move/detail/config_begin.hpp>
#include <boost/move/core.hpp> #include <boost/move/utility_core.hpp>
#include <boost/move/detail/meta_utils.hpp> #include <boost/move/traits.hpp>
#include <boost/static_assert.hpp>
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED) #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
namespace boost { namespace boost {
template<class T>
struct enable_move_utility_emulation
{
static const bool value = true;
};
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
// move() // move_if_noexcept()
// //
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
template <class T> template <class T>
inline typename ::boost::move_detail::enable_if_c inline typename ::boost::move_detail::enable_if_c
< enable_move_utility_emulation<T>::value && !has_move_emulation_enabled<T>::value, T&>::type < enable_move_utility_emulation<T>::value && !has_move_emulation_enabled<T>::value
move(T& x) BOOST_NOEXCEPT , typename ::boost::move_detail::add_const<T>::type &
>::type
move_if_noexcept(T& x) BOOST_NOEXCEPT
{ {
return x; return x;
} }
template <class T> template <class T>
inline typename ::boost::move_detail::enable_if_c inline typename ::boost::move_detail::enable_if_c
< enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value, rv<T>&>::type < enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value
move(T& x) BOOST_NOEXCEPT && ::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value, rv<T>&>::type
move_if_noexcept(T& x) BOOST_NOEXCEPT
{ {
return *static_cast<rv<T>* >(::boost::move_detail::addressof(x)); return *static_cast<rv<T>* >(::boost::move_detail::addressof(x));
} }
template <class T> template <class T>
inline typename ::boost::move_detail::enable_if_c inline typename ::boost::move_detail::enable_if_c
< enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value, rv<T>&>::type < enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value
move(rv<T>& x) BOOST_NOEXCEPT && ::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value
, rv<T>&
>::type
move_if_noexcept(rv<T>& x) BOOST_NOEXCEPT
{ {
return x; return x;
} }
//////////////////////////////////////////////////////////////////////////////
//
// forward()
//
//////////////////////////////////////////////////////////////////////////////
template <class T> template <class T>
inline typename ::boost::move_detail::enable_if_c inline typename ::boost::move_detail::enable_if_c
< enable_move_utility_emulation<T>::value && ::boost::move_detail::is_rv<T>::value, T &>::type < enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value
forward(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT && !::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value
, typename ::boost::move_detail::add_const<T>::type &
>::type
move_if_noexcept(T& x) BOOST_NOEXCEPT
{ {
return const_cast<T&>(x); return x;
} }
template <class T> template <class T>
inline typename ::boost::move_detail::enable_if_c inline typename ::boost::move_detail::enable_if_c
< enable_move_utility_emulation<T>::value && !::boost::move_detail::is_rv<T>::value, const T &>::type < enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value
forward(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT && !::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value
, typename ::boost::move_detail::add_const<T>::type &
>::type
move_if_noexcept(rv<T>& x) BOOST_NOEXCEPT
{ {
return x; return x;
} }
@@ -90,8 +91,7 @@
namespace boost{ namespace boost{
using ::std::move; using ::std::move_if_noexcept;
using ::std::forward;
} //namespace boost } //namespace boost
@@ -99,89 +99,35 @@
namespace boost { namespace boost {
//! This trait's internal boolean `value` is false in compilers with rvalue references
//! and true in compilers without rvalue references.
//!
//! A user can specialize this trait for a type T to false to SFINAE out `move` and `forward`
//! so that the user can define a different move emulation for that type in namespace boost
//! (e.g. another Boost library for its types) and avoid any overload ambiguity.
template<class T>
struct enable_move_utility_emulation
{
static const bool value = false;
};
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
// move // move_if_noexcept()
// //
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
#if defined(BOOST_MOVE_DOXYGEN_INVOKED) #if defined(BOOST_MOVE_DOXYGEN_INVOKED)
//! This function provides a way to convert a reference into a rvalue reference //! This function provides a way to convert a reference into a rvalue reference
//! in compilers with rvalue references. For other compilers converts T & into //! in compilers with rvalue references. For other compilers converts T & into
//! <i>::boost::rv<T> &</i> so that move emulation is activated. //! <i>::boost::rv<T> &</i> so that move emulation is activated. Reference
//! would be converted to rvalue reference only if input type is nothrow move
//! constructible or if it has no copy constructor. In all other cases const
//! reference would be returned
template <class T> template <class T>
rvalue_reference move(input_reference) noexcept; rvalue_reference move_if_noexcept(input_reference) noexcept;
#elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
//Old move approach, lvalues could bind to rvalue references
template <class T>
inline typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT
{ return t; }
#else //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES #else //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
template <class T> template <class T>
inline typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT inline typename ::boost::move_detail::if_c
{ return static_cast<typename ::boost::move_detail::remove_reference<T>::type &&>(t); } < ::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value
, T&&
#endif //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES , const T&
>::type
////////////////////////////////////////////////////////////////////////////// move_if_noexcept(T& x) BOOST_NOEXCEPT
//
// forward
//
//////////////////////////////////////////////////////////////////////////////
#if defined(BOOST_MOVE_DOXYGEN_INVOKED)
//! This function provides limited form of forwarding that is usually enough for
//! in-place construction and avoids the exponential overloading for
//! achieve the limited forwarding in C++03.
//!
//! For compilers with rvalue references this function provides perfect forwarding.
//!
//! Otherwise:
//! * If input_reference binds to const ::boost::rv<T> & then it output_reference is
//! ::boost::rv<T> &
//!
//! * Else, output_reference is equal to input_reference.
template <class T> output_reference forward(input_reference) noexcept;
#elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
//Old move approach, lvalues could bind to rvalue references
template <class T>
inline T&& forward(typename ::boost::move_detail::identity<T>::type&& t) BOOST_NOEXCEPT
{ return t; }
#else //Old move
template <class T>
inline T&& forward(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT
{ return static_cast<T&&>(t); }
template <class T>
inline T&& forward(typename ::boost::move_detail::remove_reference<T>::type&& t) BOOST_NOEXCEPT
{ {
//"boost::forward<T> error: 'T' is a lvalue reference, can't forward as rvalue."; return ::boost::move(x);
BOOST_STATIC_ASSERT(!boost::move_detail::is_lvalue_reference<T>::value);
return static_cast<T&&>(t);
} }
#endif //BOOST_MOVE_DOXYGEN_INVOKED #endif //BOOST_MOVE_DOXYGEN_INVOKED
} //namespace boost { } //namespace boost {

View File

@@ -0,0 +1,197 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2012-2012.
// 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.
//
//////////////////////////////////////////////////////////////////////////////
//! \file
//! This header defines core utilities to ease the development
//! of move-aware functions. This header minimizes dependencies
//! from other libraries.
#ifndef BOOST_MOVE_MOVE_UTILITY_CORE_HPP
#define BOOST_MOVE_MOVE_UTILITY_CORE_HPP
#include <boost/move/detail/config_begin.hpp>
#include <boost/move/core.hpp>
#include <boost/move/detail/meta_utils.hpp>
#include <boost/static_assert.hpp>
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
namespace boost {
template<class T>
struct enable_move_utility_emulation
{
static const bool value = true;
};
//////////////////////////////////////////////////////////////////////////////
//
// move()
//
//////////////////////////////////////////////////////////////////////////////
template <class T>
inline typename ::boost::move_detail::enable_if_c
< enable_move_utility_emulation<T>::value && !has_move_emulation_enabled<T>::value, T&>::type
move(T& x) BOOST_NOEXCEPT
{
return x;
}
template <class T>
inline typename ::boost::move_detail::enable_if_c
< enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value, rv<T>&>::type
move(T& x) BOOST_NOEXCEPT
{
return *static_cast<rv<T>* >(::boost::move_detail::addressof(x));
}
template <class T>
inline typename ::boost::move_detail::enable_if_c
< enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value, rv<T>&>::type
move(rv<T>& x) BOOST_NOEXCEPT
{
return x;
}
//////////////////////////////////////////////////////////////////////////////
//
// forward()
//
//////////////////////////////////////////////////////////////////////////////
template <class T>
inline typename ::boost::move_detail::enable_if_c
< enable_move_utility_emulation<T>::value && ::boost::move_detail::is_rv<T>::value, T &>::type
forward(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT
{
return const_cast<T&>(x);
}
template <class T>
inline typename ::boost::move_detail::enable_if_c
< enable_move_utility_emulation<T>::value && !::boost::move_detail::is_rv<T>::value, const T &>::type
forward(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT
{
return x;
}
} //namespace boost
#else //#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
#if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
#include <utility>
namespace boost{
using ::std::move;
using ::std::forward;
} //namespace boost
#else //!BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE
namespace boost {
//! This trait's internal boolean `value` is false in compilers with rvalue references
//! and true in compilers without rvalue references.
//!
//! A user can specialize this trait for a type T to false to SFINAE out `move` and `forward`
//! so that the user can define a different move emulation for that type in namespace boost
//! (e.g. another Boost library for its types) and avoid any overload ambiguity.
template<class T>
struct enable_move_utility_emulation
{
static const bool value = false;
};
//////////////////////////////////////////////////////////////////////////////
//
// move
//
//////////////////////////////////////////////////////////////////////////////
#if defined(BOOST_MOVE_DOXYGEN_INVOKED)
//! This function provides a way to convert a reference into a rvalue reference
//! in compilers with rvalue references. For other compilers converts T & into
//! <i>::boost::rv<T> &</i> so that move emulation is activated.
template <class T>
rvalue_reference move(input_reference) noexcept;
#elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
//Old move approach, lvalues could bind to rvalue references
template <class T>
inline typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT
{ return t; }
#else //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
template <class T>
inline typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT
{ return static_cast<typename ::boost::move_detail::remove_reference<T>::type &&>(t); }
#endif //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
//////////////////////////////////////////////////////////////////////////////
//
// forward
//
//////////////////////////////////////////////////////////////////////////////
#if defined(BOOST_MOVE_DOXYGEN_INVOKED)
//! This function provides limited form of forwarding that is usually enough for
//! in-place construction and avoids the exponential overloading for
//! achieve the limited forwarding in C++03.
//!
//! For compilers with rvalue references this function provides perfect forwarding.
//!
//! Otherwise:
//! * If input_reference binds to const ::boost::rv<T> & then it output_reference is
//! ::boost::rv<T> &
//!
//! * Else, output_reference is equal to input_reference.
template <class T> output_reference forward(input_reference) noexcept;
#elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
//Old move approach, lvalues could bind to rvalue references
template <class T>
inline T&& forward(typename ::boost::move_detail::identity<T>::type&& t) BOOST_NOEXCEPT
{ return t; }
#else //Old move
template <class T>
inline T&& forward(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT
{ return static_cast<T&&>(t); }
template <class T>
inline T&& forward(typename ::boost::move_detail::remove_reference<T>::type&& t) BOOST_NOEXCEPT
{
//"boost::forward<T> error: 'T' is a lvalue reference, can't forward as rvalue.";
BOOST_STATIC_ASSERT(!boost::move_detail::is_lvalue_reference<T>::value);
return static_cast<T&&>(t);
}
#endif //BOOST_MOVE_DOXYGEN_INVOKED
} //namespace boost {
#endif //#if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
#endif //BOOST_NO_CXX11_RVALUE_REFERENCES
#include <boost/move/detail/config_end.hpp>
#endif //#ifndef BOOST_MOVE_MOVE_UTILITY_CORE_HPP

View File

@@ -63,6 +63,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_move_return", "doc_move
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
EndProjectSection EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "move_if_noexcept_test", "move_if_noexcept_test.vcproj", "{CD57C283-1862-42FE-BF87-B96D3A2A7912}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global Global
GlobalSection(SolutionConfiguration) = preSolution GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug Debug = Debug
@@ -135,6 +139,10 @@ Global
{7C1462C8-D532-4B8E-F2F6-E3A2A796D912}.Debug.Build.0 = Debug|Win32 {7C1462C8-D532-4B8E-F2F6-E3A2A796D912}.Debug.Build.0 = Debug|Win32
{7C1462C8-D532-4B8E-F2F6-E3A2A796D912}.Release.ActiveCfg = Release|Win32 {7C1462C8-D532-4B8E-F2F6-E3A2A796D912}.Release.ActiveCfg = Release|Win32
{7C1462C8-D532-4B8E-F2F6-E3A2A796D912}.Release.Build.0 = Release|Win32 {7C1462C8-D532-4B8E-F2F6-E3A2A796D912}.Release.Build.0 = Release|Win32
{CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.ActiveCfg = Debug|Win32
{CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.Build.0 = Debug|Win32
{CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.ActiveCfg = Release|Win32
{CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.Build.0 = Release|Win32
EndGlobalSection EndGlobalSection
GlobalSection(SolutionItems) = postSolution GlobalSection(SolutionItems) = postSolution
..\..\..\..\boost\move\algorithm.hpp = ..\..\..\..\boost\move\algorithm.hpp ..\..\..\..\boost\move\algorithm.hpp = ..\..\..\..\boost\move\algorithm.hpp
@@ -149,6 +157,7 @@ Global
..\..\..\..\boost\move\detail\move_helpers.hpp = ..\..\..\..\boost\move\detail\move_helpers.hpp ..\..\..\..\boost\move\detail\move_helpers.hpp = ..\..\..\..\boost\move\detail\move_helpers.hpp
..\..\..\..\boost\move\traits.hpp = ..\..\..\..\boost\move\traits.hpp ..\..\..\..\boost\move\traits.hpp = ..\..\..\..\boost\move\traits.hpp
..\..\..\..\boost\move\utility.hpp = ..\..\..\..\boost\move\utility.hpp ..\..\..\..\boost\move\utility.hpp = ..\..\..\..\boost\move\utility.hpp
..\..\..\..\boost\move\utility_core.hpp = ..\..\..\..\boost\move\utility_core.hpp
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection EndGlobalSection

View File

@@ -0,0 +1,135 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="move_if_noexcept_test"
ProjectGUID="{CD57C283-1862-42FE-BF87-B96D3A2A7912}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/move_if_noexcept_test"
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="TRUE"
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_if_noexcept_test_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/move_if_noexcept_test.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_if_noexcept_test"
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_if_noexcept_test.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="{7EA34951-57AC-6216-05A6-20A754202AFF}">
<File
RelativePath="..\..\test\move_if_noexcept.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

229
test/move_if_noexcept.cpp Normal file
View File

@@ -0,0 +1,229 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Antony Polukhin 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/utility.hpp>
#include <boost/core/lightweight_test.hpp>
#include "../example/movable.hpp"
#include "../example/copymovable.hpp"
#include <boost/static_assert.hpp>
//////////////////////////////////////////////////////////////////////////////
//A copy_movable_noexcept class
class copy_movable_noexcept
{
BOOST_COPYABLE_AND_MOVABLE(copy_movable_noexcept)
int value_;
public:
copy_movable_noexcept() : value_(1){}
//Move constructor and assignment
copy_movable_noexcept(BOOST_RV_REF(copy_movable_noexcept) m)
{ value_ = m.value_; m.value_ = 0; }
copy_movable_noexcept(const copy_movable_noexcept &m)
{ value_ = m.value_; }
copy_movable_noexcept & operator=(BOOST_RV_REF(copy_movable_noexcept) m)
{ value_ = m.value_; m.value_ = 0; return *this; }
copy_movable_noexcept & operator=(BOOST_COPY_ASSIGN_REF(copy_movable_noexcept) m)
{ value_ = m.value_; return *this; }
bool moved() const //Observer
{ return value_ == 0; }
};
namespace boost{
template<>
struct has_nothrow_move<copy_movable_noexcept>
{
static const bool value = true;
};
} //namespace boost{
//////////////////////////////////////////////////////////////////////////////
//A movable_throwable class
class movable_throwable
{
BOOST_MOVABLE_BUT_NOT_COPYABLE(movable_throwable)
int value_;
public:
movable_throwable() : value_(1){}
//Move constructor and assignment
movable_throwable(BOOST_RV_REF(movable_throwable) m)
{ value_ = m.value_; m.value_ = 0; }
movable_throwable & operator=(BOOST_RV_REF(movable_throwable) m)
{ value_ = m.value_; m.value_ = 0; return *this; }
bool moved() const //Observer
{ return !value_; }
int value() const //Observer
{ return value_; }
};
//////////////////////////////////////////////////////////////////////////////
// Helper functions
movable function(movable m)
{
return movable(boost::move_if_noexcept(m));
}
copy_movable function(copy_movable m)
{
return copy_movable(boost::move_if_noexcept(m));
}
copy_movable_noexcept function(copy_movable_noexcept m)
{
return copy_movable_noexcept(boost::move_if_noexcept(m));
}
movable_throwable function(movable_throwable m)
{
return movable_throwable(boost::move_if_noexcept(m));
}
movable functionr(BOOST_RV_REF(movable) m)
{
return movable(boost::move_if_noexcept(m));
}
movable function2(movable m)
{
return boost::move_if_noexcept(m);
}
BOOST_RV_REF(movable) function2r(BOOST_RV_REF(movable) m)
{
return boost::move_if_noexcept(m);
}
movable move_return_function2 ()
{
return movable();
}
movable move_return_function ()
{
movable m;
return (boost::move_if_noexcept(m));
}
#define BOOST_CHECK(x) if (!(x)) { return __LINE__; }
int main()
{
{
movable m;
movable m2(boost::move_if_noexcept(m));
BOOST_CHECK(m.moved());
movable m3(function(movable(boost::move_if_noexcept(m2))));
BOOST_CHECK(m2.moved());
movable m4(function(boost::move_if_noexcept(m3)));
BOOST_CHECK(m3.moved());
BOOST_CHECK(!m4.moved());
}
{
movable m;
movable m2(boost::move_if_noexcept(m));
BOOST_CHECK(m.moved());
movable m3(functionr(movable(boost::move_if_noexcept(m2))));
BOOST_CHECK(m2.moved());
movable m4(functionr(boost::move_if_noexcept(m3)));
BOOST_CHECK(m3.moved());
BOOST_CHECK(!m4.moved());
}
{
movable m;
movable m2(boost::move_if_noexcept(m));
BOOST_CHECK(m.moved());
movable m3(function2(movable(boost::move_if_noexcept(m2))));
BOOST_CHECK(m2.moved());
movable m4(function2(boost::move_if_noexcept(m3)));
BOOST_CHECK(m3.moved());
BOOST_CHECK(!m4.moved());
}
{
movable m;
movable m2(boost::move_if_noexcept(m));
BOOST_CHECK(m.moved());
movable m3(function2r(movable(boost::move_if_noexcept(m2))));
BOOST_CHECK(m2.moved());
movable m4(function2r(boost::move_if_noexcept(m3)));
BOOST_CHECK(m3.moved());
BOOST_CHECK(!m4.moved());
}
{
movable m;
movable m2(boost::move_if_noexcept(m));
BOOST_CHECK(m.moved());
BOOST_CHECK(!m2.moved());
movable m3(move_return_function());
BOOST_CHECK(!m3.moved());
}
{
movable m;
movable m2(boost::move_if_noexcept(m));
BOOST_CHECK(m.moved());
BOOST_CHECK(!m2.moved());
movable m3(move_return_function2());
BOOST_CHECK(!m3.moved());
}
// copy_movable may throw during move, so it must be copied
{
copy_movable m;
copy_movable m2(boost::move_if_noexcept(m));
BOOST_CHECK(!m.moved());
copy_movable m3(function(copy_movable(boost::move_if_noexcept(m2))));
BOOST_CHECK(!m2.moved());
copy_movable m4(function(boost::move_if_noexcept(m3)));
BOOST_CHECK(!m3.moved());
BOOST_CHECK(!m4.moved());
}
// copy_movable_noexcept can not throw during move
{
copy_movable_noexcept m;
copy_movable_noexcept m2(boost::move_if_noexcept(m));
BOOST_CHECK(m.moved());
copy_movable_noexcept m3(function(copy_movable_noexcept(boost::move_if_noexcept(m2))));
BOOST_CHECK(m2.moved());
copy_movable_noexcept m4(function(boost::move_if_noexcept(m3)));
BOOST_CHECK(m3.moved());
BOOST_CHECK(!m4.moved());
}
// movable_throwable can not throw during move but it has no copy constructor
{
movable_throwable m;
movable_throwable m2(boost::move_if_noexcept(m));
BOOST_CHECK(m.moved());
movable_throwable m3(function(movable_throwable(boost::move_if_noexcept(m2))));
BOOST_CHECK(m2.moved());
movable_throwable m4(function(boost::move_if_noexcept(m3)));
BOOST_CHECK(m3.moved());
BOOST_CHECK(!m4.moved());
}
return boost::report_errors();
}
#include <boost/move/detail/config_end.hpp>