Date: Fri, 23 Feb 2024 13:02:44 +0000
Imagine if C++ had a new operator called '{mangled}', which sits just
above 'sizeof' on the operator precedence table, which must be
followed by a type in parentheses, for example:
{mangled(std::mutex)} expands to St5mutex
{"mangled(std::mutex)"} expands to "St5mutex"
The latter behaves exactly like a string literal, such that you can do:
std::stringstream ss;
char const *str = "_ZTV" {"mangled(decltype(ss))"};
and it's as if you wrote:
std::stringstream ss;
char const *str = "_ZTV"
"NSt7__cxx1118basic_stringstreamIcSt11char_traitsIcESaIcEEE";
which of course is the same as:
std::stringstream ss;
char const *str =
"_ZTVNSt7__cxx1118basic_stringstreamIcSt11char_traitsIcESaIcEEE";
What would make it more interesting though is if we could use it with
'extern' as follows:
#include <sstream>
int main(void)
{
std::stringstream ss;
// On the next line, we declare the mangled name of the vtable
extern void (*_ZTV{mangled(decltype(ss))})(void);
// On the next line, we get the address of the vtable
void (**vtable)(void*) = &_ZTV{mangled(decltype(ss))};
vtable[0](&ss); // Invoke the destructor
::new(&ss) std::stringstream(); // Invoke the constructor
}
above 'sizeof' on the operator precedence table, which must be
followed by a type in parentheses, for example:
{mangled(std::mutex)} expands to St5mutex
{"mangled(std::mutex)"} expands to "St5mutex"
The latter behaves exactly like a string literal, such that you can do:
std::stringstream ss;
char const *str = "_ZTV" {"mangled(decltype(ss))"};
and it's as if you wrote:
std::stringstream ss;
char const *str = "_ZTV"
"NSt7__cxx1118basic_stringstreamIcSt11char_traitsIcESaIcEEE";
which of course is the same as:
std::stringstream ss;
char const *str =
"_ZTVNSt7__cxx1118basic_stringstreamIcSt11char_traitsIcESaIcEEE";
What would make it more interesting though is if we could use it with
'extern' as follows:
#include <sstream>
int main(void)
{
std::stringstream ss;
// On the next line, we declare the mangled name of the vtable
extern void (*_ZTV{mangled(decltype(ss))})(void);
// On the next line, we get the address of the vtable
void (**vtable)(void*) = &_ZTV{mangled(decltype(ss))};
vtable[0](&ss); // Invoke the destructor
::new(&ss) std::stringstream(); // Invoke the constructor
}
Received on 2024-02-23 13:02:57