I have a function class method, ValueHolder::printValue
class ValueHolder {
public:
void printValue ();
} ;
How do I determine its mangled name at compile time (or runtime).
For instance I would like to do this:
const char *mangled_name = GetMangledNameOfSymbol(&ValueHolder::printValue);
This function might return a string like:
"_ZN11ValueHolder10printValueEv"
As per @Marco A. A prerequisite is a modern compiler. One that supports typeid, and with flags turned on to enable this feature.
I will also accept an answer which can work in practicality for Gcc & Clang, and a stub for MSVC.
Well what you can do is compile your C++ program using g++ and get the .o file. Run the 'nm' command on the .o file thus obtained to get the mangled names! This method is viable on Linux systems.
To prevent the C++ compiler from mangling the name of a function, you can apply the extern "C" linkage specifier to the declaration or declarations, as shown in the following example: extern "C" { int f1(int); int f2(int); int f3(int); };
Name mangling is the encoding of function and variable names into unique names so that linkers can separate common names in the language. Type names may also be mangled. Name mangling is commonly used to facilitate the overloading feature and visibility within different scopes.
linux gnu tool chain nm command can be used to see mangled name.
There's no standard way of doing this, according to [lib.type.info]
The class type_info describes type information generated by the implementation. Objects of this class effectively store a pointer to a name for the type, and an encoded value suitable for comparing two types for equality or collating order. The names, encoding rule, and collating sequence for types are all unspecified and may differ between programs.
and to your compiler implementation you could use typeid(type/expression).name()
but it is nowhere specified or enforced that this name will be decorated (it is implementation-defined). It also depends on the compilation flags used (thanks malat).
Example:
class ValueHolder {
public:
void printValue();
};
int main() {
std::cout << typeid(&ValueHolder::printValue).name();
}
gcc7.0
M11ValueHolderFvvE
clang4.0
M11ValueHolderFvvE
MSVC14
void (__cdecl ValueHolder::*)(void) __ptr64
I'll add an answer, but I'm not going to mark it correct. It is not complete. Too big to add as a comment. This is something along the lines which I can do, but I'm looking for a better way. And, yes, very tacky-hacky. But I figure there is some API somewhere which, although still will be a bit gross, will be guaranteed to work (if using a single compiler throughout a project).
template<typename R, typename C, typename... A>
struct MemberFunctionPointer
{
typedef R Return;
typedef C Class;
};
template<typename R, typename C, typename... A>
constexpr auto inferMemberFunctionPointer(R (C::*method)(A...))
{
return MemberFunctionPointer<R,C,A...>{};
}
template<typename M, M m, typename... A>
class GenerateMethodSignature
{
typedef typename decltype(inferMemberFunctionPointer(m))::Class T;
typedef typename decltype(inferMemberFunctionPointer(m))::Return R;
public:
static const char *mangledName (const char *fs)
{
const char *ts = typeid(T).name();
const char *rs = typeid(R).name();
const char *ms = typeid(M).name();
std::string r = "_Z";
if (ts[0] != 'N')
r += "N";
r += ts;
if (ts[0] == 'N')
r.pop_back();
r += std::to_string(strlen(fs));
r += fs;
r += "E";
r += ms + strlen ("M") + strlen(ts) + strlen ("F") + strlen(rs);
r.pop_back();
printf("calculated signature %s\n", r.c_str());
// this is very bad but... for demonstration purposes
return strdup(r.c_str());
}
} ;
namespace MyNamespace {
namespace MySubNamespace {
class MyClass
{
public:
int MyFunction (int myarg);
} ;
} // namespace
} // namespace
#define ExportSignature(T, M) GenerateMethodSignature<decltype(&T::M), &T::M>::mangledName(#M)
const char *myMethodSignature = ExportSignature(MyNamespace::MySubNamespace::MyClass, MyFunction);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With