Stringifying template arguments

前端 未结 8 1558
花落未央
花落未央 2020-12-04 17:00

Is it possible in C++ to stringify template arguments? I tried this:

#define STRINGIFY(x) #x

template 
struct Stringify
{
     Stringify()         


        
相关标签:
8条回答
  • 2020-12-04 17:27

    Here’s what I do: I have a demangle() function (implemented on top of abi::__cxa_demangle() which I call with a couple of convenience template function overloads, nameof(), with either the type I want stringified or an instance of same.

    It’s fairly compact, so I’ll reproduce it here in all its glory. In demangle.hh we have:

    #pragma once
    #include <typeinfo>
    
    namespace terminator {
    
        /// actual function to demangle an allegedly mangled thing
        char const* demangle(char const* const symbol) noexcept;
    
        /// convenience function template to stringify a name of a type,
        /// either per an explicit specialization:
        ///     char const* mytypename = terminator::nameof<SomeType>();
        template <typename NameType>
        char const* nameof() {
            try {
                return demangle(typeid(NameType).name());
            } catch (std::bad_typeid const&) {
                return "<unknown>";
            }
        }
    
        ///  … or as implied by an instance argument:
        ///     char const* myinstancetypename = terminator::nameof(someinstance);
        template <typename ArgType>
        char const* nameof(ArgType argument) {
            try {
                return demangle(typeid(argument).name());
            } catch (std::bad_typeid const&) {
                return "<unknown>";
            }
        }
    
    } /* namespace terminator */
    

    … And then in demangle.cpp:

    #include "demangle.hh"
    
    #include <cstdlib>
    #include <cxxabi.h>
    #include <mutex>
    #include <memory>
    
    namespace terminator {
    
        namespace {
    
            /// define one singular, private, static std::mutex,
            /// to keep the demangler from reentering itself
            static std::mutex mangle_barrier;
    
            /// define a corresponding private and static std::unique_ptr,
            /// using a delete-expression to reclaim the memory malloc()'ed by
            /// abi::__cxa_demangle() upon its return.
            /// … we use clang pragmas to add flags locally for this to work:
            #pragma clang diagnostic push
            #pragma clang diagnostic ignored "-Wglobal-constructors"
            #pragma clang diagnostic ignored "-Wexit-time-destructors"
            std::unique_ptr<char, decltype(std::free)&> demangled_name{ nullptr, std::free };
            #pragma clang diagnostic pop
    
        }
    
        char const* demangle(char const* const symbol) noexcept {
            if (!symbol) { return "<null>"; }
            std::lock_guard<std::mutex> lock(mangle_barrier);
            int status = -4;
            demangled_name.reset(
                abi::__cxa_demangle(symbol,
                                    demangled_name.get(),
                                    nullptr, &status));
            return ((status == 0) ? demangled_name.release() : symbol);
        }
    
    } /* namespace terminator */
    

    To use this, I think you’ll have to link to libc++ (or whatever your local equivalent is) to use abi::__cxa_demangle(). What may be suboptimal for the OP is the fact that this does the demangling and stringification at runtime. I’d personally love something constexpr-friendly in leu of this, but since I suffer from a severe macro-abuse allergy, I find this to be the least generally-unreasonable solution to this problem.

    (the terminator namespace is inconsequential – I use this code in a libunwind-based stacktracer called from termination handler – feel free to s///g that token)

    0 讨论(0)
  • 2020-12-04 17:30

    This breaks one of my primary tenets of C++ code writing: Avoid using tricks in both the template features and the preprocessor at the same time.

    Part of the reason for templates and the nastiness they introduce into the language was an attempt to wean developers away from using the preprocessor. If you use both, then the terrorists win.

    0 讨论(0)
提交回复
热议问题