LUMIERA.clone/research/try.cpp
Ichthyostega 7ed8486774 Library: rework detection of ''same object''
We use the memory address to detect reference to ''the same language object.''
While primarily a testing tool, this predicate is also used in the
core application at places, especially to prevent self-assignment
and to handle custom allocations.

It turns out that actually we need two flavours for convenient usage
 - `isSameObject` uses strict comparison of address and accepts only references
 - `isSameAdr` can also accept pointers and even void*, but will dereference pointers
This leads to some further improvements of helper utilities related to memory addresses...
2024-11-15 00:11:14 +01:00

134 lines
3.2 KiB
C++

/* try.cpp - to try out and experiment with new features....
* scons will create the binary bin/try
*/
// 11/24 - how to define a bare object location comparison predicate
// 11/23 - prototype for grouping from iterator
/** @file try.cpp
* Attempt to generalise the util::isSameObject, to support a mix of pointers and references.
* This is a long standing requirement, yet I made several failed attempts in the past,
* due to difficulties detecting a pointer after perfect-forwarding the argument. However,
* it is not even necessary to perfect-forward, if all we want is to extract the raw address.
*
* To my defence, I should add that I never took the time to conduct a proper experiment
* in a stand-alone setup; investigating directly in "lib/util.hpp" is a waste of time.
*/
typedef unsigned int uint;
#include "lib/format-cout.hpp"
#include "lib/test/test-helper.hpp"
#include "lib/test/diagnostic-output.hpp"
#include "lib/util.hpp"
#include <utility>
#include <string>
using lib::rani;
using std::move;
using std::string;
template<class X>
inline const void*
getAd (X& x)
{
return static_cast<const void*> (std::addressof(x));
}
template<class X>
inline const void*
getAd (X* x)
{
return static_cast<const void*> (x);
}
template<class A, class B>
inline bool
isSameOb (A const& a, B const& b)
{
return getAd(a)
== getAd(b);
}
struct Boo
{
string moo;
short goo;
Boo(short uh)
: moo{util::toString(uh-1)}
, goo(uh+1)
{ }
operator string() const
{
return moo+util::toString(goo);
}
};
struct SuBoo : Boo
{
long poo = rani(goo);
using Boo::Boo;
};
inline Boo*
asBoo (void* mem)
{// type tag to mark memory address as Buffer
return static_cast<Boo*> (mem);
}
int
main (int, char**)
{
Boo boo(23);
Boo booo(23);
Boo* boop = &boo;
Boo const* const beep = boop;
cout << boo << endl;
SHOW_EXPR(util::showAdr(getAd(boo )))
SHOW_EXPR(util::showAdr(getAd(&boo)))
SHOW_EXPR(util::showAdr(getAd(boop)))
SHOW_EXPR(util::showAdr(getAd(beep)))
SHOW_EXPR(isSameOb(boop, beep))
SHOW_EXPR(isSameOb(&boop, &beep))
SHOW_EXPR(isSameOb(boo, beep))
SHOW_EXPR(isSameOb(*beep, booo))
SHOW_EXPR(isSameOb(boo, boo.moo))
SHOW_EXPR(isSameOb(boo, &boo.moo))
SHOW_EXPR(isSameOb(boo.moo, booo))
SHOW_EXPR(isSameOb(booo, asBoo(&booo.moo)))
SHOW_EXPR(isSameOb(booo, asBoo(&booo.goo)))
const void* voo = boop;
SHOW_EXPR(isSameOb(voo, boo))
SHOW_EXPR(isSameOb(voo, boop))
SHOW_EXPR(isSameOb(voo, asBoo(&boo.moo)))
SHOW_EXPR(isSameOb(voo, asBoo(&booo.moo)))
SHOW_EXPR(isSameOb(voo, asBoo(&boo.goo)))
Boo&& roo = move(boo);
SHOW_EXPR(isSameOb(roo, boo))
SHOW_EXPR(isSameOb(voo, roo))
SHOW_EXPR(isSameOb(voo, Boo{roo}))
SuBoo* suBoo = static_cast<SuBoo*>(&boo);
SHOW_EXPR(isSameOb(boo, suBoo))
SHOW_EXPR(isSameOb(boo, suBoo->moo))
SHOW_EXPR(isSameOb(voo, suBoo->moo))
SHOW_EXPR(isSameOb(voo, suBoo->poo))
SuBoo sudo{*suBoo};
SHOW_EXPR(isSameOb(sudo, suBoo))
suBoo = &sudo;
SHOW_EXPR(isSameOb(sudo.poo, suBoo->poo))
cout << "\n.gulp.\n";
return 0;
}