防止 C++03 代码在 C++11 中表现不佳的好方法?
Good way to prevent C++03 code from performing suboptimally in C++11?
我有一些C++03代码为某些类实现了swap
,以使std::sort
(和其他函数)快速完成。
对我来说不幸的是,std::sort
现在似乎使用std::move
,这意味着我的代码现在比 C++03 中慢得多。
我知道我可以使用#if __cplusplus >= 201103L
有条件地定义移动构造函数/移动赋值运算符,但我想知道是否有更好的不使用预处理器黑客的方法?
(我想避免使用proprocessor黑客,因为它们会很丑陋,因为我不仅要测试像_MSC_VER >= 1600
这样的编译器版本,而且还因为它们不能很好地与LZZ等无法识别C++11移动语法但迫使我预处理代码的工具一起使用。
似乎真正的问题是:如何使用 C++03 编译器实现移动构造函数和移动赋值?
简单的答案是:他们不能!然而,简单的答案忽略了创建完全有效的 C++03 代码的可能性,这些代码成为移动构造函数并使用 C++11 编译器移动赋值。这种方法需要使用一些预处理器黑客,但该位仅用于创建一个标头,定义用于实际实现的一些工具。
这是一个简单的头文件,它很高兴地编译,没有任何警告,clang和gcc启用或禁用C++11:
// file: movetools.hpp
#ifndef INCLUDED_MOVETOOLS
#define INCLUDED_MOVETOOLS
INCLUDED_MOVETOOLS
namespace mt
{
#if __cplusplus < 201103L
template <typename T>
class rvalue_reference {
T* ptr;
public:
rvalue_reference(T& other): ptr(&other) {}
operator T&() const { return *this->ptr; }
};
#else
template <typename T>
using rvalue_reference = T&&;
#endif
template <typename T>
rvalue_reference<T> move(T& obj) {
return static_cast<rvalue_reference<T> >(obj);
}
}
#endif
基本功能是定义一个模板mt::rvalue_reference<T>
它的行为有点像 C++03 中的右值引用,实际上是 C++11 的右值引用(即T&&
)。它不会完全处理 C++03 右值引用,但至少允许定义移动构造函数和移动赋值,而无需实际使用右值引用。
请注意,mt::move()
只是用于稍后展示即使在 C++03 中也可以移动rvalue_reference<T>
!重点是rvalue_reference<T>
要么是 C++03 编译器理解的东西,要么是T&&
的东西。对于这种相当合理的表示法,编译器必须支持别名模板。如果不是这种情况,则可以应用相同的技巧,但使用相应类模板的合适嵌套类型。
下面是此标头的示例用法:
#include "movetools.hpp"
#include <iostream>
class foo
{
public:
foo() { std::cout << "foo::foo()n"; }
foo(foo const&) { std::cout << "foo::foo(const&)n"; }
foo(mt::rvalue_reference<foo> other) {
std::cout << "foo::foo(&&)n";
this->swap(other);
}
~foo() { std::cout << "foo::~foo()n"; }
foo& operator= (foo const& other) {
std::cout << "foo::operator=(foo const&)n";
foo(other).swap(*this);
return *this;
}
foo& operator= (mt::rvalue_reference<foo> other) {
std::cout << "foo::operator=(foo&&)n";
this->swap(other);
return *this;
}
void swap(foo&) {
std::cout << "foo::swap(foo&)n";
}
};
int main()
{
foo f0;
foo f1 = f0;
foo f2 = mt::move(f0);
f1 = f2;
f0 = mt::move(f1);
}
也就是说,实际的业务逻辑没有任何预处理器黑客攻击。唯一需要对预处理器进行修改是在标头movetools.hpp
中,不需要弄乱。也就是说,我实际上认为它没有使用预处理器黑客来定义实际的移动构造函数或移动赋值,尽管预处理器在某处使用。如果您坚持不想使用宏黑客,可以通过指示编译器查看不同的标头来完成,但这是movetools.hpp
的实现细节。
看看 Boost.Move。它具有针对 c++03 的移动仿真。也许它可以提供帮助,但我没有看细节。
- 使用不同的CRT将新的C++代码与旧的(二进制)组件隔离开来的最佳方法是什么
- 当无法使用模板和宏时,生成类型变体C++代码的最简单方法是什么?
- 有没有一种代码密度较低的方法来使用非默认构造函数初始化数组?
- 如何重写全局方法名称以在调用原始方法之前将我的代码推到前面
- 在nodejs中使用本机代码的最佳方法是什么?
- 函数从唯一代码调用正确的子类方法
- 如何启用使用另一个类的静态方法的模板函数的自动推导,从而消除冗长的调用方代码
- 有没有更好的方法来编写这个c++代码
- 终端进程终止,退出代码为:1有什么方法可以修复它吗
- 有没有一种预处理器的方法可以从调试符号中删除代码段
- C++:销毁此代码的最佳方法是什么?
- 在.cpp文件中定义方法而不是在 C++ 的 .h 文件中定义方法时,如何提高代码的性能?
- 为什么在我的代码中没有调用 g 模拟方法
- 设计许多单例代码结构的更好方法
- 两种专用方法中的相同代码
- Android 无法从本机代码调用 Java 方法 JNI
- 我的类中有方法的指针数组,但我不能调用我的方法.代码如下
- 如何在子类中获得相同的方法代码而不重复代码
- 如何只执行一次方法代码,尽管每帧调用一次
- 模板化的方法代码在哪里分配?