2016-12-31 47 views
1

我想利用类构造函数和解构函数来通过RAII成语在我的日志文件中表示和格式化作用域。使用单个#define,它会打印“{”并增加全局缩进级别,以便下一个记录行将在该缩进级别打印。防止解构宏定义的匿名变量,直到范围结束

LogScopeRAII应该打印“}”并自然减少全局缩进级别,因为它在Foo()的末尾超出了范围。但是,我所看到的行为是LogScopeRAII在构建后立即被解构。

假设:我认为这个问题是一个正在上分配的RHS创建LogScopeRAII(因而匿名?),并在该行的末尾被销毁,但我不知道该怎么办关于。我认为LOG_ANONYMOUS_VARIABLEVSCOPE_F会做到这一点,并导致它坚持下去,但事实并非如此。

问题:如何阻止LogScopeRAII被解构,直到调用函数超出范围?

/* Header */ 
LogScopeRAII::LogScopeRAII(Verbosity verbosity, const char* file, unsigned line, const char* format, ...) 
{ 
    // ... 
    // print "{" and then increase an indentation global var 
} 

LogScopeRAII::~LogScopeRAII() 
{ 
    // ... 
    // print "}" and then decrease the indentation global var 
} 

#define LOG_ANOMYMOUS_VARIABLE(str) LOG_CONCAT(str, __LINE__) 

#define VSCOPE_F(verbosity, ...) \ 
LogScopeRAII LOG_ANONYMOUS_VARIABLE(raii) = \ 
((verbosity) > verb_cutoff() ? LogScopeRAII() : LogScopeRAII{verbosity, __FILE__, __LINE__, __VA_ARGS__} 

#define SCOPE_F(verbosity_name, ...) VSCOPE_F(Verbosity_ ## verbosity_name, __VA_ARGS__) 

#define SCOPE_FUNCTION(INFO) SCOPE_F(verbosity_name, __FUNCTION__) 

/* Implementation */ 
void Foo() 
{ 
    SCOPE_FUNCTION(INFO) // print "{" and increase indentation 
    for (size_t i = 0; i < 3; ++i) 
    { 
     // do work 
     LOG(INFO, "Work logged"); 
    } 
    // print "}" and decrease indentation 
} 

希望的输出:

{ Foo() 
    "Work Logged" // Note indentation 
} 0.23 s: Foo() 

编辑:煮ISSUE DOWN

的它的关键是这样的:所述三元似乎并不奏效。

这工作:

LogScopeRAII a(LogScopeRAII{ Verbosity_INFO, __FILE__, static_cast<unsigned>(__LINE__), "" }); 

但这并不:

LogScopeRAII a(((Verbosity_INFO) > indent) ? LogScopeRAII() : LogScopeRAII{ Verbosity_INFO, __FILE__, static_cast<unsigned>(__LINE__), "" }); 

我得到:

{ 
} 
Work logged 
Work logged 
Work logged 
} 
constructCounter: 1 
destructCounter: 2 
Exiting... 
+1

馅这个在这一点上宏是有点为时过早。在实际的代码中分解出来,按照你想要的方式工作,然后根据需要添加宏。 –

+0

请参阅编辑。接受你的建议。似乎三元不工作? – Stradigos

+1

也许LogScopeRAII的移动结构被打破。 “工作版本”将隐藏由于复制影响而导致的问题,但是没有使用条件运算符版本的副本。至少需要在析构函数中有代码才能发出'}',如果这是一个已经被移出的临时文件等。 –

回答

1
#define VSCOPE_F(verbosity, ...) \ 
LogScopeRAII LOG_ANONYMOUS_VARIABLE(raii) = \ 
((verbosity) > verb_cutoff() ? LogScopeRAII() : LogScopeRAII{verbosity, __FILE__, __LINE__, __VA_ARGS__} 

应该

#define VSCOPE_F(verbosity, ...) \ 
LogScopeRAII LOG_ANONYMOUS_VARIABLE(raii) \ 
(((verbosity) > verb_cutoff() ? LogScopeRAII() : LogScopeRAII{verbosity, __FILE__, __LINE__, __VA_ARGS__}) 

否则你使用临时变量的拷贝构造函数。

(你也可能会解决您移动,构造函数和析构函数,让你的当前宏)

+0

这似乎没有什么区别。但是,如果我删除了三元操作,只需使用参数LogScopeRAII即可运行。三元组有什么不对?我确认它正在评估相同的LogScopeRAII - 带参数的LogScopeRAII - 无论哪种方式,所以这是别的。它不断地构造和解构,然后再解构一次......这很奇怪,因为没有匹配的构造函数可以使用它。不知道这怎么可能。这里是我的测试设置的一个pastebin:http://pastebin.com/8mSjVnPN – Stradigos

+0

最终,这是一个MSVC C++ 14的问题,因为它在GCC中完美工作。我想它不会在GCC中产生副本,但会在MSVC中产生副本。请参阅:http://stackoverflow.com/questions/22078029/why-does-the-ternary-operator-prevent-return-value-optimization和http://stackoverflow.com/questions/11914691/copy-elision-move- constructor-not-called-when-using-ternary-expression-in-retur我在适当的地方添加了static_cast 来修复它。好奇的是,如果有更好的办法,但问题仍然得到解决。感谢您的帮助。 – Stradigos