在 C++03 中模拟 lambda 以实现宏中的流量控制目的

问题描述 投票:0回答:1

我的头文件中有一些现有代码,需要在 C++03 和 C++11 的上下文中使用

它定义了一个宏

TABORT
,它接受
printf
样式的格式字符串和要使用该字符串格式化的参数,将结果打印到
stdout
,然后调用
std::abort

本质上,类似于

#define TABORT(...) do { fprintf(stderr, "Aborting at %s:%d for reason: ", __FILE__, __LINE__); fprintf(stderr, __VA_ARGS__); std::abort(); } while(0)

我想添加一些逻辑来捕获计算

__VA_ARGS__
会引发异常的情况,从而阻止对
std::abort
的调用。例如,在以下内容中:

if (SomethingReallyBadHappened())
    TABORT("Aborting because %s", GetReallyBadDetails().c_str());

如果

GetReallyBadDetails
抛出异常,我想确保调用中止(此处,而不是在某些异常展开之后)。

所以,我做了类似的事情:

#define TABORT(...) do { fprintf(stderr, "Aborting at %s:%d for reason: ", __FILE__, __LINE__); try { fprintf(stderr, __VA_ARGS__); } catch (...) { fprintf(stderr, "<Failed to evaluate abort message>\n"); } std::abort(); } while(0)

但是,当在标记为 __forceinline 的函数中使用宏时,这会导致 Visual Studio 中出现

C4714 警告
,可能是由于

在某些情况下,编译器不会内联特定函数 机械原因。例如,编译器不会内联:

  • 带有 try(C++ 异常处理)语句的函数。

因此,为了避免该警告(并保持先前确定需要内联的内联函数inlined[我希望这与分析一起完成......]),我正在考虑做类似的事情

// In header

// Assume this is like std::function except construction from a lambda can't throw
template <typename Sig>
class function_ref;
using PrintAbortMsg = function_ref<void(const char*)>;
void [[noreturn]] do_tabort(const char* file, int line, function_ref<void(PrintAbortMsg &)> msgGenerator) noexcept;
#define TABORT(...) do_tabort(__FILE__, __LINE__, [&](PrintAbortMsg& print) { print(SprintfToStdString(__VA_ARGS__).c_str()); })

// In cpp

void do_tabort(const char* file, int line, function_ref<void(PrintAbortMsg&)> msgGenerator) noexcept
{
    fprintf(stderr, "Aborting at %s:%d for reason: ", __FILE__, __LINE__);
    try
    {
        msgGenerator([](const char* msg) { fprintf(stderr, "%s\n", msg); });
    }
    catch (...)
    {
        fprintf(stderr, "<Failed to evaluate abort message>\n");
    }
    std::abort();
}

我认为可以在 C++11 的上下文中工作,但我不确定如何做一些适用于 C++03 的事情。我不想触及该宏的现有用法。

c++ visual-studio c++11 macros c++03
1个回答
0
投票
当恐龙在地球上漫步时,甚至在 C++03 之前,构造函数和析构函数在 C++ 中的工作方式是相同的,就像现在一样。

struct abort_no_matter_what { ~abort_no_matter_what() { std::abort(); } };
现在,一旦 

abort_no_matter_what

 构建完毕,你的鹅就熟了:

{ abort_no_matter_what i_said; // Some code }
有问题的

某些代码最终总是会调用std::abort

。当执行正常离开作用域时;或者当抛出异常时,因为堆栈展开将调用析构函数,该析构函数将调用 
std::abort
 并掩盖事物。

所以,现在,你的宏就变成了:

#define TABORT(...) do { abort_no_matter_what i_said; \ fprintf(stderr, "Aborting at %s:%d for reason: ", __FILE__, __LINE__); \ fprintf(stderr, __VA_ARGS__); } while(0)
    
© www.soinside.com 2019 - 2024. All rights reserved.