我在玩GCC(4.9.2)abi::__ cxa_demangle,结果发现无法分解特定符号名称。该符号是:_ZNK12DebugWrapperIR5TestClsE5getIdIIEEEDTcldtcl7declvalIS1_EEL_ZNKS0_5getIdEvEspfp_EEDpOT_我很惊讶在那里看到“declval”。该特定功能使用以下宏定义:template <typename WrappedType>class DebugWrapper{private:WrappedType VALUE;std::string NAME;mutable std::string CALLER;public:...#define WRAP_CONST_FUNCTION(name, enterLogging, exitLogging) \ template <typename ...Args> \ auto name(Args&&... args) const -> decltype(std::declval<WrappedType>().name(args...)) \ { \ \ struct dummy \ { \ const char* const FUNCTION = nullptr; \ const std::string& CALLER; \ const WrappedType& VALUE; \ \ dummy( const char* const input, \ const std::string& caller, \ const WrappedType& value): \ FUNCTION(input), CALLER(caller), VALUE(value) \ { \ enterLogging; \ } \ \ ~dummy() \ { \ exitLogging; \ } \ }dummy(#name, CALLER, VALUE); \ \ return VALUE.name(args...); \ } WRAP_CONST_FUNCTION(getId, <whatever>, <whatever>)...};我还通过itanium c++ abi spec快速搜索了declval,但没有结果。为什么在那儿?为何abi::__ cxa_demangle无法解散呢? 最佳答案 模板函数需要使其返回类型出现在整齐的名称中,因为模板函数可以仅在返回类型上重载。一个简单的例子是template <typename T> void f() { }template <typename T> auto g() -> decltype(f<T>()) { }inline void h() { }int main() { g<int>(); h(); }编译此代码并检查输出,我看到:$ g++ -c h.cc -std=c++11 && nm h.o | c++filt0000000000000000 T main0000000000000000 W decltype ((f)()) g()0000000000000000 W h()You can see the return type there for g, but not for h. The fact that h is not a template function already means there cannot be another function h in the same namespace with the same parameters.This is also why getId appears twice in your mangled name. One of those is the name itself, the other is coming from its appearance in the return type.declval is not special here, which is why it's not called out in the C++ ABI. Any function, library or user, gets treated the same way.As for why it won't demangle, it's hard to tell. A real code example that generates the mangled name in your question would help here, but the 5TestCls looks wrong, as the number that precedes a name indicates the length, and I do get the impression that TestCls was supposed to be the full name. If that was indeed the name, then the demangling fails because the mangled name is invalid.Based on the complete example, the one that you posted in the comments, I can come up with a reduced program, and it seems like it's the member access operator that's not handled properly by the demangler:extern struct A { void f(); static void g(); } a;template <typename...T> auto f(T...t) -> decltype(a.f(t...));template <typename...T> auto g(T...t) -> decltype(A::g(t...));int main() { f(); g(); }$ g++ -std = c++ 11 -pedantic -c h.cc && nm h.o && nm -C h.o0000000000000000 T主 U _Z1fIJEEDTcldtL_Z1aEL_ZN1A1fEvEspfp_EEDpT_ U _Z1gIJEEDTclL_ZN1A1gEvEspfp_EEDpT_0000000000000000 T主 U _Z1fIJEEDTcldtL_Z1aEL_ZN1A1fEvEspfp_EEDpT_ U十进制类型(A::g({parm#1} ...))g ()_Z1fIJEEDTcldtL_Z1aEL_ZN1A1fEvEspfp_EEDpT_和_Z1gIJEEDTclL_ZN1A1gEvEspfp_EEDpT_之间的区别通过一些额外的间距更加明显:_Z1fIJEEDTcldtL_Z1aEL_ZN1A1fEvEspfp_EEDpT__Z1gIJEEDTcl L_ZN1A1gEvEspfp_EEDpT_唯一的区别是f与g和dtL_Z1aE。Itanium C++ ABI指定将x.y修改为dt <expression> <unresolved-name>。在这里,<expression>是L_Z1aE。那部分看起来不错。这表示a全局变量的“混杂”(不是真的)名称。但是<unresolved-name>是_ZN1A1fEvE。错了正确的是decltype(A::g(t...))版本,其中函数调用运算符的最左侧操作数可以通过<expr-primary> ::= L <mangled-name> E产生形式表示为错误的名称,但不适用于decltype(a.f(t...))版本。这将意味着类似于A::f(),但是<unresolved-name>不应具有 namespace 限定符,除非它们实际出现在源代码中,并且即使在那时也仅具有特殊前缀(sr)。它也不应该具有参数信息。 <unresolved-name>应该只是1f。如果使用了更正的名称,则分解器可以处理它:$ c++ filt decltype((a.f)({parm#1} ...))f ()clang确实会生成正确的名称,就像在Coliru上看到的那样,只需在命令调用中将g++更改为clang++即可。您可能需要将此错误报告给GCC开发人员。关于c++ - 为什么在整齐的符号名称中出现declval?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30329367/
10-11 09:27
查看更多