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

Get return type of function in macro (C++)

本文关键字:函数 返回类型 c++ 获取      更新时间:2023-10-16

我有ASSERT(x)宏,如果它断言(在发布配置中),我想调用return。要做到这一点,我需要知道返回类型的函数,我使用这个ASSERT。如何得到它(我处理C++03, LLVM GCC 4.2编译器)?

My ASSERT宏:

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

PS:我尝试了return 0; -编译器显示错误的void函数(我没有尝试复杂的返回类型),如果return; -错误的非void函数。

(更新…)

我将回答 werwindle nyarlathotepjd - jan de Vaan。我使用标准assert进行调试配置。但在beta测试后,我仍然会收到最终用户的崩溃报告,在大多数情况下,我需要更改崩溃函数:

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

我明白,我的程序可能会崩溃(否则它肯定会在当前功能中崩溃)。我也不能退出应用程序,因为开发是针对iPhone的(应用程序可能不会退出编程)。因此,最简单的方法是在断言失败时"自动返回"。

在宏中不能确定周围函数的返回类型;宏是由预处理器展开的,预处理器并没有这些宏发生的环境信息;它基本上只是"搜索和替换"宏。您必须为每种返回类型编写单独的宏。

但为什么不退出程序(即调用exit函数)?仅仅从函数返回似乎不是一个非常健壮的错误处理。毕竟,失败的断言应该只在出现严重错误时才会发生(这意味着程序处于一种它没有设计来处理的状态),因此最好尽快退出程序。

在c语言中没有合适的方法来确定函数内部的返回类型。

同样,如果您以某种方式实现ASSERT的变体,它将导致错误的程序行为。ASSERT的主要思想:如果失败,则程序处于未定义状态,唯一正确的方法是现在停止它。即通过调用exit()

我认为你可以用模板函数来做到这一点,你可以在宏中调用default(x)。

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

将适用于所有具有默认构造函数的内容。我认为你需要为void写一个特殊的宏。

我希望我的模板语法是正确的,我的c++越来越生疏了。

你不能这样做,C/c++预处理器是非常基本的,它不能做任何代码分析。您最多只能将返回类型传递给宏。

但是我的观点是:你使用断言的方式是错误的。它们应该只用于代码的完整性检查(对于程序员可能导致的错误);如果所有的断言都通过了,你不需要关心它们,你不需要记录它们。

不仅如此,而且(一般来说)你应该使用最不意外的元素。您是否期望ASSERT记录一些东西,然后强制使函数返回?我知道我不会。我要么期望它完全关闭应用程序(标准assert所做的),要么让我决定接下来会发生什么(也许我有一些指针可以释放)。

宏没有return值,因为它们本身不是函数。它们替换了使用它们的源代码,因此您可以在使用宏的函数中使用return

没有办法从宏中获得return value

您可以根据需要定义另一个宏。

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

然后在函数内部:

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
}

就这么做

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

我相信你在试图解决错误的问题。如果你不想让你的程序在断言的情况下崩溃,你最好改进你的测试。

在这些断言中使用'return'会给您一种错误的安全感。相反,它隐藏了你的问题,并在你的程序中引起意想不到的行为,所以你得到的bug要复杂得多。我的一个同事为此写了一篇很好的博客。

如果你真的想要它,你可以试着写return {};,让它默认构造这个值,或者有一个assert宏,你也提供了失败的情况。但是我真的不推荐它!