2013-06-05 38 views
0

是否可以在编译时/运行时获取变量名称或枚举值名称?特别是,namespace::/class::/struct::/union:: -qualified(具有可调节深度,如同UNIX补丁程序不灵活-p/--strip=选项)。在GCC 4.8.1我可以这样写:编译时间/运行时变量名称/枚举值名称信息

#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; 
} 

但我希望能够做到以下几点:有些虚constexpr abi::__get_value_info(symbol)类的手段

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 
} 

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; 
} 

但这仅仅是对类型名称和编译时扣除太远。

我想这就是我所想到的,需要几乎嵌入到我的可执行调试器以及调试信息部分的可用性。但我仍然认为,这根本不可能。

回答

1

可能有其他的解决方案,但我通常这样做的方法是用#define语句

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 
} 
+0

你知道任何的替代品在这里×宏?我即将使用x宏进行制作,而我真的很害怕我必须回到这个位置。所有这些宏是邪恶的帖子吓唬我这么多! – NicoBerrogorry

+1

我在生产代码中使用过这几次 - 它从来都不是问题。维护起来要容易得多。您不会得到冗长的嵌套开关语句,编译器会告诉您添加新枚举时缺少的内容。只要尝试一个noddy程序来检查机制。如果宏是邪恶的,他们就不会把它们放在语言中。 – cup

+0

是的,我做了一些半复杂的样本和“实验室”代码,以确保它们正确,至少正确。是的,我猜如果他们在那里这是有原因的。为每个枚举器维护枚举和名称映射只是更短,更容易理解,我评论了所有接近矫枉过正的事情......但是,我的胆量告诉我这个设计存在问题,那不是预期的用于枚举。我应该写一个新问题吗? – NicoBerrogorry