0

是否可以在编译时/运行时获取变量名或枚举值名?特别是namespace::/// class::- qualified (具有可调深度,就像有UNIX补丁的统一性struct::/选项)。在gcc 4.8.1我可以写:union::-p--strip=

#include <iostream>
#include <ostream>

#include <cstdlib>

enum class mnemocode
{
    fwait,
    finit,
    fninit,
    fstsw,
    fnstsw,
    // ...
    sahf,
    ret,
    prologue,
    epilogue,
    sp_inc,
    sp_dec,
    call
};

inline /* till C++14 cannot be constexpr */
auto mnemocode_name(mnemocode _mnemocode)
{
    switch (_mnemocode) {
    case mnemocode::fwait    : return "fwait";
    case mnemocode::finit    : return "finit";
    case mnemocode::fninit   : return "fninit";
    case mnemocode::fstsw    : return "fstsw";
    case mnemocode::fnstsw   : return "fnstsw";
    // ...
    case mnemocode::sahf     : return "sahf";
    case mnemocode::ret      : return "ret";
    case mnemocode::prologue : return "prologue";
    case mnemocode::epilogue : return "epilogue";
    case mnemocode::sp_inc   : return "sp_inc";
    case mnemocode::sp_dec   : return "sp_dec";
    case mnemocode::call     : return "call";
    default : return "[unknown instruction]";
    }
}

inline
std::ostream & operator << (std::ostream & out, mnemocode _mnemocode)
{
    return out << mnemocode_name(_mnemocode);
}

int main()
{
    std::cout << mnemocode::fwait << std::endl; // fwait
    return EXIT_SUCCESS;
}

但我希望能够做到以下几点:

template< typename M, typename = typename std::enable_if< std::is_same< mnemocode, typename std::remove_reference< typename std::remove_cv< M >::type >::type >::value >
inline constexpr
auto mnemocode_name(M && _mnemocode)
{
    constexpr auto const depth = std::numeric_limits< std::size_t >::max(); // remove all qualifiers before last operator ::
    return abi::__get_value_info(_mnemocode).name(depth); // compile time if M is constexpr
}

通过一些想象的constexpr abi::__get_value_info(symbol)类。

GCC允许我写:

#include <iostream>
#include <string>
#include <type_traits>

#include <cxxabi.h>
#include <cstdlib>

template< typename T >
/* cannot be constexpr :( */
const char * this_type()
{
    return __PRETTY_FUNCTION__;
}

template< typename T >
std::string theirs_type()
{
    int status = 0;
    auto realname_(abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status));
    switch (status) {
    case -1: return "Could not allocate memory";
    case -2: return "Invalid name under the C++ ABI mangling rules";
    case -3: return "Invalid argument to demangle";
    }
    std::string os(realname_);
    std::free(realname_);
    if (std::is_volatile< T >::value) {
        os = "volatile " + os;
    }
    if (std::is_const< T >::value) {
        os += " const";
    }
    if (std::is_rvalue_reference< T >::value) {
        os += " &&";
    } else if (std::is_lvalue_reference< T >::value) {
        os += " &";
    }
    return os;
}

int main()
{
    std::cout << this_type< decltype(static_cast< double const >(double())) >() << std::endl; // const char* this_type() [with T = double]
    std::cout << theirs_type< double const && >() << std::endl; // double &&
    return EXIT_SUCCESS;
}

但这仅与类型名称有关,与编译时间推断相去甚远。

我想这就是我在这里提出的全部内容,几乎需要嵌入到我的可执行调试器中以及带有调试信息的部分的可用性。但我仍然不认为,这根本不可能。

4

1 回答 1

1

可能还有其他解决方案,但我通常这样做的方式是使用#defines

1)在一个文件中定义你的枚举(比如 enumdef.h)

ENUMDEF(fwait)
ENUMDEF(finit)
...
ENUMDEF(call)

2) 为枚举声明一个标题

#ifndef EnumDefEnum_h
#define EnumDefEnum_h
enum mnemcode
{
#define ENUMDEF(x) x,
#include "enumdef.h"
#undef ENUMDEF
mnemcodeMax
};
#endif

3) 打印它们

#include "enumdefenum.h"
static const char* mnem_str[] =
{
#define ENUMDEF(x) #x,
#include "enumdef.h"
#undef ENUMDEF
    ""
};

const char* mnem_name(mnemcode index)
{
    return mnem_str[index];
}

4) 如果您遵守命名约定,您甚至可以在 switch 语句中使用它们

switch (index)
{
// Put in a pragma to tell you which one it is because the compiler will
// tell you the  line number in enumdef.h: not the one in this file
#pragma message("switch statement in some routine")
#define ENUMDEF(x) \
case x: Do##x(whatever); break;
#include "enumdef.h"
#undef ENUMDEF
}
于 2013-06-05T19:33:10.790 回答