C++将执行一段代码以及该代码块之后的某个命令的宏

发布于 2024-09-04 16:22:01 字数 1107 浏览 2 评论 0原文

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;
}
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
}

Only the first main() works.
I think the comments explain the issue.

It doesn't need to be a macro but to me it just sounds like a classical "macro-needed" case.

By the way, there's the BOOST_FOREACH macro/library and I think it does the exact same thing I'm trying to achieve but it's too complex for me to find the essence of what I need.
From its introductory manual page, an example:

#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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

烦人精 2024-09-11 16:22:01

最干净的方法可能是使用 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 块来实现:

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)
{
    // ...
}

I don'我真的不认为宏观方法是个好主意;如果我在生产源代码中看到这一点,我可能会感到困惑。

The cleanest way to do this is probably to use an RAII container to reset the value:

// 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_;
};

used as:

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

When the block ends, the destructor will be called, resetting the object to the specified value.

If you really want to use a macro, as long as it is a relatively simple expression, you can do this using a for-block:

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

which can be turned into a macro:

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

used as:

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

I don't really think the macro approach is a good idea; I'd probably find it confusing were I to see this in production source code.

惟欲睡 2024-09-11 16:22:01

您并不绝对需要宏 - 您可以使用内部作用域变量:

#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”,而不是外部。不过,两步舞还是有效的。

这样做的主要缺点是需要修改代码块。

如果块中存在副作用(如上面的打印语句),您可以调用包含内部块的函数。如果块中没有副作用,那么为什么要执行它呢?

#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);
}

You don't absolutely need a macro - you could use inner scope variables:

#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);
}

This produces the output:

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

If you compile with GCC and -Wshadow you get a warning; otherwise, it compiles clean.
You can't write int xyz = xyz; in the inner block reliably; once the '=' is parsed, the declaration is complete and so the initializer is the inner 'xyz', not the outer. The two step dance works, though.

The primary demerit of this is that it requires a modification in the code block.

If there are side-effects in the block - like the print statements above - you could call a function that contains the inner block. If there are no side-effects in the block, why are you executing it at all.

#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);
}
成熟的代价 2024-09-11 16:22:01

除非将循环放入宏中,否则无法使宏在循环后执行命令。认真的吗?仅仅创建一个作用域变量会是一个更好的主意。

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

在异常等情况下得到保证,而宏版本绝对不是。我更愿意使用这种模式来保证异常,因为它比仅仅复制 int 更灵活。

You can't make a macro perform a command after a loop unless you put the loop in the macro. And seriously? It would be a much better idea just to make a scoped variable.

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

Guaranteed in the cases of exception, etc, whereas the macro version most definitely isn't. I would prefer to use this pattern for the exception guarantees, and because it's more flexible than just copying the int.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文