简体   繁体   English

获取宏中函数的返回类型(C++)

[英]Get return type of function in macro (C++)

I have ASSERT(x) macro and I want to call return if it asserts (in release configuration).我有ASSERT(x)宏,如果它断言(在发布配置中),我想调用return To do this I need to know return type of function where I use this ASSERT .为此,我需要知道使用此ASSERT的函数的返回类型。 How to get it (I deal with C++03 , LLVM GCC 4.2 compiler)?如何得到它(我处理C++03LLVM GCC 4.2编译器)?

My ASSERT macro:我的断言宏:

#define ASSERT(x) \
    if(!(x)) {
        LOG ("ASSERT in %s: %d", __FILE__, __LINE__); \
        return /*return_type()*/; \
    }

PS: I tried return 0; PS:我试过return 0; - compiler shows error for void functions (and I didn't try it for complex returning types), if return; - 如果return;编译器显示 void 函数错误(我没有尝试复杂的返回类型) return; - error for non-void functions. - 非空函数的错误。

(Updated...) (更新...)

I'll answer to werewindle , nyarlathotep and jdv-Jan de Vaan here.我会在这里回答werewindlenyarlathotepjdv-Jan de Vaan I use standard assert for debug configuration.我使用标准assert进行调试配置。 But after beta-testing I still get crash reports from final customers, and in most cases I need to change my crashing functions:但是在 beta 测试之后,我仍然会收到最终客户的崩溃报告,并且在大多数情况下,我需要更改我的崩溃函数:

ASSERT (_some_condition_);
if (!_some_condition_)      // add this return
    return _default_value_;

I understand, that my program may crash probably later (otherwise it will definitely crash in current function).我知道,我的程序可能会在以后崩溃(否则它肯定会在当前函数中崩溃)。 Also I can't quit application because developing is for iPhone (apps may not quit programmatically there).我也不能退出应用程序,因为开发是针对 iPhone 的(应用程序可能不会在那里以编程方式退出)。 So the easiest way would be to "auto return" when assertion failed.所以最简单的方法是在断言失败时“自动返回”。

You can't determine the return type of the surrounding function in a Macro; 您无法确定宏中周围函数的返回类型; macros are expanded by the preprocessor, which doesn't have this kind of information about the surroundings where these macros occur; 宏由预处理器扩展,它没有关于这些宏出现的环境的这种信息; it is basically just "searching and replacing" the macros. 它基本上只是“搜索和替换”宏。 You would have to write separate macros for each return type. 您必须为每种返回类型编写单独的宏。

But why not exit the program (ie calling the exit function)? 但为什么不退出程序(即调用exit函数)? Just returning from a function doesn't seem like a very robust error handling. 刚从函数返回似乎不是一个非常强大的错误处理。 Failed assertions should after all only occur when something is terribly wrong (meaning the program is in a state it was not designed to handle), so it is best to quit the program as soon as possible . 失败的断言应该只在某些事情出现严重错误时发生(意味着程序处于不能设计处理的状态),因此最好尽快退出程序

There are no proper way to determine return type inside a function in C. 没有正确的方法来确定C中函数内的返回类型。

Also, if you somehow implement your variant of ASSERT it will lead to erroneous program behavior. 此外,如果您以某种方式实现ASSERT的变体,它将导致错误的程序行为。 Main idea of ASSERT : if it fails, then program is in undefined state and only proper way is to stop it now. ASSERT主要思想:如果失败,那么程序处于未定义状态,只有正确的方法是立即停止它。 Ie by calling exit() . 即通过调用exit()

You can't do that, the C/C++ preprocessor is pretty basic and it can't do any code analysis. 你不能这样做,C / C ++预处理器非常基础,不能进行任何代码分析。 At most what you can do is pass the return type to the macro. 您最多可以将返回类型传递给宏。

But here's my opinion: you're using assertions the wrong way. 但是我的意见是:你使用错误的方式使用断言。 They should only be used for sanity checks of the code (for errors than can only happen because of the programmer); 它们只应用于代码的健全性检查(对于错误而言,只能由于程序员而发生); if all assertions pass, you don't need to care about them, you don't need to log them. 如果所有断言都通过,你不需要关心它们,你不需要记录它们。

And not only that, but (in general) you should employ the element of least surprise. 不仅如此,而且(一般而言)你应该使用最少惊喜的元素。 Do you expect ASSERT to log something and then forcefully make the function return? 你期望ASSERT记录一些东西然后强行让函数返回吗? I know I wouldn't. 我知道我不会。 I either expect it to close the application completely (what the standard assert does) or let me decide what happens next (maybe I have some pointers to free). 我要么完全关闭应用程序(标准assert做什么),要么让我决定接下来会发生什么(也许我有一些免费的指针)。

Just do this就这样做

#define ASSERT(x, ret, type)    \
     if(!(x)){
          LOG ("ASSERT in %s: %d", __FILE__, __LINE__); \
          return (type) ret;
     }

I believe you are trying to solve the wrong problem.我相信您正在尝试解决错误的问题。 You don't want your program to crash in case of assertions, you best improve your testing.你不希望你的程序在断言的情况下崩溃,你最好改进你的测试。

Having a 'return' in these assertions give you a false sense of security.在这些断言中有“回报”会给你一种虚假的安全感。 Instead it hides your problems and causes unexpected behavior in your program so the bugs you do get are much more complex.相反,它隐藏了您的问题并导致程序中出现意外行为,因此您遇到的错误要复杂得多。 A colleague of mine actually wrote a good blog post about it.我的一位同事实际上写了一篇很好的博客文章

If you really would want it, you could try writing return {};如果你真的想要它,你可以尝试写return {}; so it default constructs the value, or have an assert macro where you also provide the failure case.所以它默认构造值,或者有一个断言宏,您还可以在其中提供失败案例。 However I really don't recommend it!不过我真的不推荐!

Macros do not return values, as they are no functions per se. 宏不return值,因为它们本身不是函数。 They substitute the source code where they are used, so you'd return in the function where the macro is used. 它们替换使用它们的源代码,因此您将return使用宏的函数。

There is no way to get the return value from a macro. 无法从宏获取return value

i think you can do this with a template function, that you call default(x) from within the macro. 我认为您可以使用模板函数执行此操作,您可以在宏中调用default(x)。

template<class T> default<T>(T x) { return T(); }

that will work for everyting with a default constructor. 这将适用于默认构造函数的每一个。 I think you need to write a special macro for void. 我认为你需要为void编写一个特殊的宏。

I hope i got the template syntax right, my c++ is getting rusty. 我希望我的模板语法正确,我的c ++正在生锈。

You could just define another macro for your needs. 您可以根据需要定义另一个宏。

#define ASSERT(x) \
    if(!(x)) { \
        LOG ("ASSERT in %s: %d", __FILE__, __LINE__); \
        ASSERT_DEFAULT_RETURN(); \
    }

And then inside a function: 然后在一个函数内:

int foo(){
#ifdef ASSERT_DEFAULT_RETURN
#undef ASSERT_DEFAULT_RETURN
#endif
#define ASSERT_DEFAULT_RETURN() return 0
  // ...
  ASSERT(some_expression);
  // ...
  // cleanup
#undef ASSERT_DEFAULT_RETURN
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM