Function std.exception.mayPointTo
Checks whether a given source object contains pointers or references to a given target object.
bool mayPointTo(S, T, Tdummy)
(
auto const ref S source,
const ref T target
) pure nothrow @trusted
if (__traits(isRef, source) || isDynamicArray!S || isPointer!S || is(S == class));
bool mayPointTo(S, T)
(
auto const shared ref S source,
const shared ref T target
) pure nothrow @trusted;
Parameters
Name | Description |
---|---|
source | The source object |
target | The target object |
Returns
true
if source
's representation embeds a pointer
that points to target
's representation or somewhere inside
it.
If source
is or contains a dynamic array, then, then these functions will check
if there is overlap between the dynamic array and target
's representation.
If source
is a class, then it will be handled as a pointer.
If target
is a pointer, a dynamic array or a class, then these functions will only
check if source
points to target
, not what target
references.
If source
is or contains a union, then there may be either false positives or
false negatives:
doesPointTo
will return true
if it is absolutely certain
source
points to target
. It may produce false negatives, but never
false positives. This function should be prefered when trying to validate
input data.
mayPointTo
will return false
if it is absolutely certain
source
does not point to target
. It may produce false positives, but never
false negatives. This function should be prefered for defensively choosing a
code path.
Note
Evaluating doesPointTo(x, x)
checks whether x
has
internal pointers. This should only be done as an assertive test,
as the language is free to assume objects don't have internal pointers
(TDPL 7.1.3.5).
Example
Pointers
int i = 0;
int* p = null;
assert(!p .doesPointTo(i));
p = &i;
assert( p .doesPointTo(i));
Example
Structs and Unions
struct S
{
int v;
int* p;
}
int i;
auto s = S(0, &i);
// structs and unions "own" their members
// pointsTo will answer true if one of the members pointsTo.
assert(!s .doesPointTo(s .v)); //s.v is just v member of s, so not pointed.
assert( s .p .doesPointTo(i)); //i is pointed by s.p.
assert( s .doesPointTo(i)); //which means i is pointed by s itself.
// Unions will behave exactly the same. Points to will check each "member"
// individually, even if they share the same memory
Example
Arrays (dynamic and static)
int i;
int* p = &i; // trick the compiler when initializing slicep; https://issues.dlang.org/show_bug.cgi?id=18637
int[] slice = [0, 1, 2, 3, 4];
int[5] arr = [0, 1, 2, 3, 4];
int*[] slicep = [p];
int*[1] arrp = [&i];
// A slice points to all of its members:
assert( slice .doesPointTo(slice[3]));
assert(!slice[0 .. 2] .doesPointTo(slice[3])); // Object 3 is outside of the
// slice [0 .. 2]
// Note that a slice will not take into account what its members point to.
assert( slicep[0] .doesPointTo(i));
assert(!slicep .doesPointTo(i));
// static arrays are objects that own their members, just like structs:
assert(!arr .doesPointTo(arr[0])); // arr[0] is just a member of arr, so not
// pointed.
assert( arrp[0] .doesPointTo(i)); // i is pointed by arrp[0].
assert( arrp .doesPointTo(i)); // which means i is pointed by arrp
// itself.
// Notice the difference between static and dynamic arrays:
assert(!arr .doesPointTo(arr[0]));
assert( arr[] .doesPointTo(arr[0]));
assert( arrp .doesPointTo(i));
assert(!arrp[] .doesPointTo(i));
Example
Classes
class C
{
this(int* p){this .p = p;}
int* p;
}
int i;
C a = new C(&i);
C b = a;
// Classes are a bit particular, as they are treated like simple pointers
// to a class payload.
assert( a .p .doesPointTo(i)); // a.p points to i.
assert(!a .doesPointTo(i)); // Yet a itself does not point i.
//To check the class payload itself, iterate on its members:
()
{
import std .traits : Fields;
foreach (index, _; Fields!C)
if (doesPointTo(a .tupleof[index], i))
return;
assert(0);
}();
// To check if a class points a specific payload, a direct memmory check
// can be done:
auto aLoc = cast(ubyte[__traits(classInstanceSize, C)]*) a;
assert(b .doesPointTo(*aLoc)); // b points to where a is pointing