Meh*_*dad 9 c++ move-semantics c++11 c++03
使用这个答案,我发明了自己的基于C++ 03模拟移动语义的方法swap.
首先,我检测移动语义(即C++ 03的可用性):
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) || \
defined(_MSC_VER) && _MSC_VER >= 1600
#define HAS_MOVE_SEMANTICS 1
#elif defined(__clang)
#if __has_feature(cxx_rvalue_references)
#define HAS_MOVE_SEMANTICS 1
#else
#define HAS_MOVE_SEMANTICS 0
#endif
#else
#define HAS_MOVE_SEMANTICS 0
#endif
Run Code Online (Sandbox Code Playgroud)
然后我有条件地定义一个名为的宏move:
#if !HAS_MOVE_SEMANTICS
#include <algorithm>
namespace _cpp11_detail
{
template<bool B, class T = void> struct enable_if;
template<class T> struct enable_if<false, T> { };
template<class T> struct enable_if<true, T> { typedef T type; };
template<class T>
inline char (&is_lvalue(
T &, typename std::allocator<T>::value_type const volatile &))[2];
inline char (&is_lvalue(...))[1];
template<bool LValue, class T>
inline typename enable_if<!LValue, T>::type move(T v)
{ T r; using std::swap; swap(r, v); return r; }
template<bool LValue, class T>
inline typename enable_if<LValue, T>::type move(T &v)
{ T r; using std::swap; swap(r, v); return r; }
template<bool LValue, class T>
inline typename enable_if<LValue, T>::type const &move(T const &v)
{ return v; }
}
using _cpp11_detail::move;
namespace std { using _cpp11_detail::move; }
// Define this conditionally, if C++11 is not supported
#define move(...) move< \
(sizeof((_cpp11_detail::is_lvalue)((__VA_ARGS__), (__VA_ARGS__))) != 1) \
>(__VA_ARGS__)
#endif
Run Code Online (Sandbox Code Playgroud)
然后我像这样使用它:
#include <vector>
std::vector<int> test(std::vector<int> v) { return std::move(v); }
int main()
{
std::vector<int> q(5, 5);
int x = 5;
int y = std::move(x);
std::vector<int> qq = test(std::move(test(std::move(q))));
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,这种方法在实践中有多安全?(假设它编译好)
是否有任何实际场景可能无法在C++ 03中正常工作但在C++ 11中无法正常工作?
反之亦然 - 它可以在C++ 11中正常工作但在C++ 03中失败吗?
(注意:我正在寻找一个实际的答案,而不是语言律师的答案.我知道定义新成员在namespace std技术上是未定义的,但在实践中不会导致任何编译器出现问题,所以我找不到为了这个问题的目的值得担心.我担心偶然的悬挂引用等情况.)