【发布时间】:2010-08-18 05:10:40
【问题描述】:
是否有任何符合标准的方法可以用宏模拟“返回”?
目前,我正在尝试使用 C++ 中的宏包装 _alloca 函数以模拟堆栈上的可变长度数组(C99 支持)。由于 _alloca 函数操作堆栈指针,我认为内联函数不适合这个时候。
下面是我写的当前代码。
template <typename T>
inline void __placement_new_array(T arr[], const size_t size) {
assert(size > 0);
for (size_t i = 0; i < size; i++) {
new (&arr[i]) T;
}
}
template <typename T>
class __arraydtor
{
public:
__arraydtor(T arr[], size_t size) : arr_(arr), size_(size) {}
~__arraydtor() {
for (size_t i = size_ - 1; i != (size_t)(-1); i--) {
arr_[i].~T();
}
}
private:
T* arr_;
size_t size_;
};
#define stack_alloc(size) _alloca(size)
#define stacknew(ptr, type, size) \
ptr = static_cast<type*>(stack_alloc(sizeof(type) * size));\
__placement_new_array(ptr, size);\
__arraydtor<type> __##type##_dtor_instance(ptr,size)
...
type* pos;
stacknew(pos, type, size);
我认为即使现在代码也相当可用(至少在 vs2005 中它适用于大多数类型),但最终我想实现可以像下面这样使用的宏 -
pos = stacknew(type, size);
(当然 pos = stacknew type[size]; 会更酷,但我认为没有办法使用任何 C++ 编译器来实现它)
由于宏包含一些声明,在当前形式下模拟“return”是不可能的——它可能是不可能的或需要不同的方法。但是我对宏的使用经验不足,无法判断是否可以。
我还想指出,当目标数组的 ctor 抛出异常时,上面的代码是不安全的 - 如果有人提出改进宏的方法,我也将不胜感激。
【问题讨论】:
-
忘记 C++ 中存在宏。是的,它们很诱人,但它们使本已晦涩难懂的语言变得更糟。如果很难编码,它会更难理解,并且在发生变化时可能会中断。
-
@msw,+1 是为了避免使用宏,减去数十亿是为了使用“更糟糕”这个短语。不是真的,只是 +1 :-)
-
我从斯伯丁·格雷那里偷了“更糟”的东西,所以我什至不能相信这句话。如果你开始在谈话中使用它,我也不应该承担责任(你会使用它,它很好地从舌头上掉下来)。
-
通常我和你一样是宏观批评家,尽量避免使用它。但是在这种情况下,我不能使用函数、类或除宏之外的任何其他抽象机制来避免代码重复,这比精心设计/使用的宏更邪恶(当然,这只是我的意见......)。
-
代码重用并不比宏更邪恶。