C ++ MACRO,它将在该块之后执行代码块和某个命令

时间:2010-06-06 21:21:31

标签: c++ macros c-preprocessor

void main()
{
    int xyz = 123; // original value
    { // code block starts
        xyz++;
        if(xyz < 1000)
            xyz = 1;
    } // code block ends
    int original_value = xyz; // should be 123
}

void main()
{
    int xyz = 123; // original value
    MACRO_NAME(xyz = 123) // the macro takes the code code that should be executed at the end of the block.
    { // code block starts
        xyz++;
        if(xyz < 1000)
            xyz = 1;
    } // code block ends << how to make the macro execute the "xyz = 123" statement?
    int original_value = xyz; // should be 123
}

只有第一个main()有效 我认为这些评论解释了这个问题。

它不需要是一个宏,但对我来说,它听起来像是一个经典的“宏观需要”的案例。

顺便说一下,有BOOST_FOREACH宏/库,我认为它与我想要实现的完全一样,但是找到我需要的东西对我来说太复杂了。
从其介绍性手册页中,举例:

#include <string>
#include <iostream>
#include <boost/foreach.hpp>

int main()
{
    std::string hello( "Hello, world!" );

    BOOST_FOREACH( char ch, hello )
    {
        std::cout << ch;
    }

    return 0;
}

3 个答案:

答案 0 :(得分:8)

最简洁的方法是使用RAII容器重置值:

// Assumes T's assignment does not throw
template <typename T> struct ResetValue
{
    ResetValue(T& o, T v) : object_(o), value_(v) { }
    ~ResetValue() { object_ = value_; }

    T& object_;
    T value_;
};

用作:

{
    ResetValue<int> resetter(xyz, 123);
    // ...
}

当块结束时,将调用析构函数,将对象重置为指定值。

如果确实想要使用宏,只要它是一个相对简单的表达式,就可以使用for-block执行此操作:

for (bool b = false; b == false; b = true, (xyz = 123))
{
    // ...
}

可以变成一个宏:

#define DO_AFTER_BLOCK(expr) \
    for (bool DO_AFTER_BLOCK_FLAG = false; \
         DO_AFTER_BLOCK_FLAG == false; \
         DO_AFTER_BLOCK_FLAG = true, (expr))

用作:

DO_AFTER_BLOCK(xyz = 123)
{
    // ...
}

我并不认为宏观方法是个好主意;如果我在生产源代码中看到这个,我可能会觉得很困惑。

答案 1 :(得分:2)

您不一定需要宏 - 您可以使用内部范围变量:

#include <stdio.h>
int main(void)
{
    int xyz = 123;
    printf("xyz = %d\n", xyz);
    {
        int pqr = xyz;
        int xyz = pqr;
        printf("xyz = %d\n", xyz);
        xyz++;
        if (xyz < 1000)
            xyz = 1;
        printf("xyz = %d\n", xyz);
    }
    printf("xyz = %d\n", xyz);
    return(0);
}

这会产生输出:

xyz = 123
xyz = 123
xyz = 1
xyz = 123

如果您使用GCC和-Wshadow进行编译,则会收到警告;否则,它编译清洁。 你不能可靠地在内部块中写int xyz = xyz;;一旦'='被解析,声明就完成了,因此初始化器是内部'xyz',而不是外部。然而,这两步舞蹈有效。

这主要是因为它需要修改代码块。

如果块中有副作用 - 就像上面的print语句一样 - 你可以调用一个包含内部块的函数。如果块中没有副作用,为什么要执行它。

#include <stdio.h>
static void inner(int xyz)
{
    printf("xyz = %d\n", xyz);
    xyz++;
    if (xyz < 1000)
        xyz = 1;
    printf("xyz = %d\n", xyz);
}

int main(void)
{
    int xyz = 123;
    printf("xyz = %d\n", xyz);
    inner(xyz);
    printf("xyz = %d\n", xyz);
    return(0);
}

答案 2 :(得分:0)

除非将循环放在宏中,否则不能使宏在循环后执行命令。并认真?只做一个范围变量会更好。

template<typename T> class CallFunctionOnScopeExit {
    T t;
public:
    CallFunctionOnScopeExit(T tt) : t(tt) {}
    ~CallFunctionOnScopeExit() { t(); }
};

在例外等情况下保证,而宏版本绝对不是。我更喜欢将此模式用于异常保证,因为它比仅复制int更灵活。