Date: Tue, 2 Apr 2024 16:46:57 +0000
I think we need to take a closer look at this person with a clearly fake identity and their real motivations, as I personally don't believe in this paradoxical character that seems extremely proficient at certain things like hijacking the exception system to do a non-trivial conversion, and yet is completely incapable of understanding basic clean code?
________________________________
From: Std-Proposals <std-proposals-bounces_at_[hidden]> on behalf of Frederick Virchanza Gotham via Std-Proposals <std-proposals_at_[hidden]>
Sent: Tuesday, April 2, 2024 5:58:12 PM
To: std-proposals <std-proposals_at_[hidden]>
Cc: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Subject: [std-proposals] Use the exception system to check for bases at runtime
Use Case 1:
You have a variable of type std::any. You want to check if the
contained value is derived from 'std::exception', and if it is, you
want to return the 'what()' string. So you start off writing a
function as follows:
char const *get_what(std::any const &a)
{
void *const pderived = pointer_from_any(a);
if ( nullptr == pderived ) return "<no info>";
auto *const pbase = base<std::exception>( pderived, a.type() );
if ( nullptr == pbase ) return "<no info>";
return pbase->what();
}
So first of all, we have an invocation of a function called
"pointer_from_any" to get the address of the contained object, which
on GNU g++ can be coded as follows:
void *pointer_from_any(std::any const &a)
{
if ( false == a.has_value() ) return nullptr;
auto const manager = (void (*)(int, std::any const*, void*))
*(void**)&a;
void *retval;
manager(0, &a, &retval);
return retval;
}
Next we have an invocation of a function called 'base', which is a
template function with the following signature:
template<class Base>
Base *base(void *const parg, std::type_info const &ti);
You give this function two pieces of information:
1) The address of an object (can be non-polymorphic or polymorphic)
2) The type_info of the object
If the object has 'Base' as a base class, it returns a valid pointer
to the base class. Otherwise it returns a nullptr.
I have coded 'base' to make use of the exception handling system. I
looked at how GNU g++ implements 'make_exception_ptr' and
'rethrow_exception', and then I wrote the following function:
template<class Base>
Base *base(void *const parg, std::type_info const &ti)
{
using namespace __cxxabiv1;
alignas(std::max_align_t) __cxa_refcounted_exception header =
{}; // all zeroes
char *pobj = static_cast<char*>(static_cast<void*>(&header + 1));
header.referenceCount = 123;
header.exc.exceptionType = const_cast<std::type_info*>(&ti);
header.exc.exceptionDestructor = [](void*){};
header.exc.unexpectedHandler =
reinterpret_cast<void(*)(void)>( std::get_terminate() );
header.exc.terminateHandler = std::get_terminate();
__GXX_INIT_PRIMARY_EXCEPTION_CLASS(header.exc.unwindHeader.exception_class);
header.exc.unwindHeader.exception_cleanup =
[](_Unwind_Reason_Code, _Unwind_Exception*){};
try
{
std::rethrow_exception(
*static_cast<std::exception_ptr*>(static_cast<void*>(&pobj)) );
}
catch(Base &obj)
{
std::ptrdiff_t const delta = pobj - (char*)&obj;
return (Base*)( (char*)parg - delta );
}
catch(...){}
return nullptr;
}
And so putting this altogether, what I'm peddling to you today is as follows:
At runtime, if you give me the address of an object along with its
type_info, I can confirm for you if any given class is one of its base
classes, and if it is, I'll give you a pointer to the base class. The
pointer will be appropriately adjusted in cases of multiple
inheritance.
Here it is working up on GodBolt with GNU g++, LLVM clang++, and Intel ICX:
https://godbolt.org/z/hvMr5WTK8
I'm hoping it can be coded for Microsoft too.
So a future standard of C++ could have the standalone template
function 'base', and also the class 'std::any' could have a member
function called 'base'.
________________________________
From: Std-Proposals <std-proposals-bounces_at_[hidden]> on behalf of Frederick Virchanza Gotham via Std-Proposals <std-proposals_at_[hidden]>
Sent: Tuesday, April 2, 2024 5:58:12 PM
To: std-proposals <std-proposals_at_[hidden]>
Cc: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Subject: [std-proposals] Use the exception system to check for bases at runtime
Use Case 1:
You have a variable of type std::any. You want to check if the
contained value is derived from 'std::exception', and if it is, you
want to return the 'what()' string. So you start off writing a
function as follows:
char const *get_what(std::any const &a)
{
void *const pderived = pointer_from_any(a);
if ( nullptr == pderived ) return "<no info>";
auto *const pbase = base<std::exception>( pderived, a.type() );
if ( nullptr == pbase ) return "<no info>";
return pbase->what();
}
So first of all, we have an invocation of a function called
"pointer_from_any" to get the address of the contained object, which
on GNU g++ can be coded as follows:
void *pointer_from_any(std::any const &a)
{
if ( false == a.has_value() ) return nullptr;
auto const manager = (void (*)(int, std::any const*, void*))
*(void**)&a;
void *retval;
manager(0, &a, &retval);
return retval;
}
Next we have an invocation of a function called 'base', which is a
template function with the following signature:
template<class Base>
Base *base(void *const parg, std::type_info const &ti);
You give this function two pieces of information:
1) The address of an object (can be non-polymorphic or polymorphic)
2) The type_info of the object
If the object has 'Base' as a base class, it returns a valid pointer
to the base class. Otherwise it returns a nullptr.
I have coded 'base' to make use of the exception handling system. I
looked at how GNU g++ implements 'make_exception_ptr' and
'rethrow_exception', and then I wrote the following function:
template<class Base>
Base *base(void *const parg, std::type_info const &ti)
{
using namespace __cxxabiv1;
alignas(std::max_align_t) __cxa_refcounted_exception header =
{}; // all zeroes
char *pobj = static_cast<char*>(static_cast<void*>(&header + 1));
header.referenceCount = 123;
header.exc.exceptionType = const_cast<std::type_info*>(&ti);
header.exc.exceptionDestructor = [](void*){};
header.exc.unexpectedHandler =
reinterpret_cast<void(*)(void)>( std::get_terminate() );
header.exc.terminateHandler = std::get_terminate();
__GXX_INIT_PRIMARY_EXCEPTION_CLASS(header.exc.unwindHeader.exception_class);
header.exc.unwindHeader.exception_cleanup =
[](_Unwind_Reason_Code, _Unwind_Exception*){};
try
{
std::rethrow_exception(
*static_cast<std::exception_ptr*>(static_cast<void*>(&pobj)) );
}
catch(Base &obj)
{
std::ptrdiff_t const delta = pobj - (char*)&obj;
return (Base*)( (char*)parg - delta );
}
catch(...){}
return nullptr;
}
And so putting this altogether, what I'm peddling to you today is as follows:
At runtime, if you give me the address of an object along with its
type_info, I can confirm for you if any given class is one of its base
classes, and if it is, I'll give you a pointer to the base class. The
pointer will be appropriately adjusted in cases of multiple
inheritance.
Here it is working up on GodBolt with GNU g++, LLVM clang++, and Intel ICX:
https://godbolt.org/z/hvMr5WTK8
I'm hoping it can be coded for Microsoft too.
So a future standard of C++ could have the standalone template
function 'base', and also the class 'std::any' could have a member
function called 'base'.
-- Std-Proposals mailing list Std-Proposals_at_[hidden] https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2024-04-02 16:47:03