简体   繁体   中英

Can I use __LINE__ or __FILE__ in inline function in C++?

I faced a problem while implementing the logger.

First, I used to LINE and FILE with standard C Macro function like below

// global.h
..
namespace MyLogger {

class Logger
{
    ..
    void _write(int _level, const char* _file, int _line, const char* _fmt, ...);
};
static Logger    logger;

}; // namespace MyLogger

..

// avoid conflict..
#undef error
#undef trace

#define error(_MESSAGE_, ...) _write(LOG_LEVEL_ERROR, (const char*)__FILE__, (int)__LINE__, (const char*)_MESSAGE_, ##__VA_ARGS__)
#define info(_MESSAGE_, ...)  _write(LOG_LEVEL_INFO,  (const char*)__FILE__, (int)__LINE__, (const char*)_MESSAGE_, ##__VA_ARGS__)
#define trace(_MESSAGE_, ...) _write(LOG_LEVEL_TRACE, (const char*)__FILE__, (int)__LINE__, (const char*)_MESSAGE_, ##__VA_ARGS__)
..

// main.cpp

using namespace MyLogger;

// using like this
logger.error("- log error");
logger.info("- log info %s", "test 1");
..

In fact, it seems to work well. However, the problem occurred while using openv.

error and trace seem to conflicted with error and trace in opencv .

error: expected primary-expression before 'int' [build] CV_EXPORTS CV_NORETURN void error(int _code, const String& _err, const char* _func, const char* _file, int _line);

So I'm thinking about other methods using inline functions, not macros.

// global.h
..
    //void _write(int _level, const char* _file, int _line, const char* _fmt, ...);
    static inline void error(/* Is it possible to toss __LINE__ or __FILE__ ? */);
    static inline void info(/* .. */);
    static inline void trace(/* .. */);
..

// main.cpp
logger::error("- log error");
logger::info("%d %c %f, 1, 'A', '0.1');

Can I know the line or file of the location where the log was output through a method other than a macro?

No , inline functions/methods won't work the same as macro in this context. Macros are simply text replacement, so the __LINE__ and __FILE__ will give accurate results. So macros are your only choice ; see if you can name them better to avoid conflicts.

However the inline functions are systematically compiled subunits. So the line number and the file names will always be same that of those functions where it resides.

Refer: Inline functions vs Preprocessor macros

There are 3 stages in which C++ becomes a running program.

  1. Preprocessor
  2. Compiler
  3. Linker

__LINE__ and __FILE__ are processed by the preprocessor (stage 1). However, it's the compiler that decides about inlining (stage 2).

Other languages like C# have this in the compiler stage: [CallerMemberName] , [CallerFilePath] and [CallerLineNumber] [MSDN] but I am don't think this exists in C++ at the moment.

How about this:

#define log_error(_MESSAGE_, ...) \
    logger._write( \
        LOG_LEVEL_ERROR, \
        (const char*)__FILE__, \
        (int)__LINE__, \
        (const char*)_MESSAGE_, \
        ##__VA_ARGS__)

There is no much difference between logger.error and log_error .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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