I want to declare identifiers for scopes which will be used to automatically populate a field of any logging statements within the innermost scope. They will usually, but not always (e.g. lambdas, blocks introduced with {}), match the "name" of the enclosing block.
Usage would look something like this:
namespace app {
LOG_CONTEXT( "app" );
class Connector {
    LOG_CONTEXT( "Connector" );
    void send( const std::string &  msg )
    {
        LOG_CONTEXT( "send()" );
        LOG_TRACE( msg );
    }
};
} // namespace app
//                     not inherited
LOG_CONTEXT( "global", false );
void fn()
{
    LOG_DEBUG( "in fn" );
}
int main()
{
    LOG_CONTEXT( "main()" );
    LOG_INFO( "starting app" );
    fn();
    Connector c;
    c.send( "hello world" );
}
with the result being something like:
[2018-03-21 10:17:16.146] [info] [main()] starting app
[2018-03-21 10:17:16.146] [debug] [global] in fn
[2018-03-21 10:17:16.146] [trace] [app.Connector.send()] hello world
We can get the inner-most scope by defining the LOG_CONTEXT macro such that it declares a struct. Then in the LOG_* macros we call a static method on it to retrieve the name. We pass the whole thing to a callable object, e.g.:
namespace logging {
spdlog::logger & instance()
{
    auto sink =
        std::make_shared<spdlog::sinks::ansicolor_stdout_sink_mt>();
    decltype(sink) sinks[] = {sink};
    static spdlog::logger logger(
        "console", std::begin( sinks ), std::end( sinks ) );
    return logger;
}
// TODO: stack-able context
class log_context
{
public:
    log_context( const char *  name )
        : name_( name )
    {}
    const char * name() const
    { return name_; }
private:
    const char *  name_;
};
class log_statement
{
public:
    log_statement( spdlog::logger &           logger,
                   spdlog::level::level_enum  level,
                   const log_context &        context )
        : logger_ ( logger  )
        , level_  ( level   )
        , context_( context )
    {}
    template<class T, class... U>
    void operator()( const T &  t, U&&...  u )
    {
        std::string  fmt = std::string( "[{}] " ) + t;
        logger_.log(
            level_,
            fmt.c_str(),
            context_.name(),
            std::forward<U>( u )... );
    }
private:
    spdlog::logger &           logger_;
    spdlog::level::level_enum  level_;
    const log_context &        context_;
};
} // namespace logging
#define LOGGER ::logging::instance()
#define CHECK_LEVEL( level_name ) \
    LOGGER.should_log( ::spdlog::level::level_name )
#define CHECK_AND_LOG( level_name )      \
    if ( !CHECK_LEVEL( level_name ) ) {} \
    else                                 \
        ::logging::log_statement(        \
            LOGGER,                      \
            ::spdlog::level::level_name, \
            __log_context__::context() )
#define LOG_TRACE CHECK_AND_LOG( trace )
#define LOG_DEBUG CHECK_AND_LOG( debug )
#define LOG_INFO CHECK_AND_LOG( info )
#define LOG_WARNING CHECK_AND_LOG( warn )
#define LOG_ERROR CHECK_AND_LOG( err )
#define LOG_CRITICAL CHECK_AND_LOG( critical )
#define LOG_CONTEXT( name_ )                        \
    struct __log_context__                          \
    {                                               \
        static ::logging::log_context context()     \
        {                                           \
            return ::logging::log_context( name_ ); \
        }                                           \
    }
LOG_CONTEXT( "global" );
Where I'm stuck is building the stack of contexts to use when defining an inner-most __log_context__. We may use a differently-named structure and macro convention to add 1 or 2 levels (e.g. LOG_MODULE can define a __log_module__), but I want a more general solution. Here are the restrictions I can think of to make things easier:
- Scope nesting level may be reasonably bounded, but the user should not have to provide the current level/code may be moved to a different scope without being changed. Maybe 16 levels is enough (that gives us orgname::app::module::subsystem::subsubsystem::detail::impl::detail::util with some room to spare...)
- Number of next-level scopes within a scope (in a single translation unit) may be bounded, but should be much larger than the value for 1. Maybe 256 is reasonable, but I'm sure someone will have a counterexample.
- Ideally the same macro could be used for any context.
I have considered the following approaches:
- using __parent_context__ = __log_context__; struct __log_context__ ...- hoping that - __parent_context__picks up the outer context, but I was getting compiler errors indicating that a type name must refer unambiguously to a single type in the same scope. This restriction applies only when used in the body of a class, this would otherwise work for functions and namespaces.
- Tracking the structures applicable to a scope in something like - boost::mpl::vector- The examples in the tutorial lead me to believe I would run into the same issue as in 1, since the vector after being pushed to needs to be given a distinct name which would need to be referred to specifically in nested scopes. 
- Generating the name of the applicable outer scope with a preprocessor counter. - This would work in my simple usage example above, but would fail in the presence of discontinuous declarations in a namespace or method definitions outside of the corresponding class. 
How can this information be accessed in the nested scopes?
 
    