mayPointTo

Checks whether a given source object contains pointers or references to a given target object.

  1. bool mayPointTo(S source, T target)
    @trusted pure nothrow
    bool
    mayPointTo
    (
    S
    T
    Tdummy = void
    )
    (
    auto ref const S source
    ,
    ref const T target
    )
    if (
    __traits(isRef, source) ||
    ||
    ||
    is(S == class)
    )
  2. bool mayPointTo(S source, T target)
  3. bool doesPointTo(S source, T target)
  4. bool doesPointTo(S source, T target)

Parameters

source S

The source object

target T

The target object

Return Value

Type: bool

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 or void[n], 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).

Bugs

The function is explicitly annotated @nogc because inference could fail, see issue 17084.

Examples

Pointers

int  i = 0;
int* p = null;
assert(!p.doesPointTo(i));
p = &i;
assert( p.doesPointTo(i));

Structs and Unions

1 struct S
2 {
3     int v;
4     int* p;
5 }
6 int i;
7 auto s = S(0, &i);
8 
9 // structs and unions "own" their members
10 // pointsTo will answer true if one of the members pointsTo.
11 assert(!s.doesPointTo(s.v)); //s.v is just v member of s, so not pointed.
12 assert( s.p.doesPointTo(i)); //i is pointed by s.p.
13 assert( s  .doesPointTo(i)); //which means i is pointed by s itself.
14 
15 // Unions will behave exactly the same. Points to will check each "member"
16 // individually, even if they share the same memory

Arrays (dynamic and static)

1 int i;
2  // trick the compiler when initializing slice
3  // https://issues.dlang.org/show_bug.cgi?id=18637
4 int* p = &i;
5 int[]  slice = [0, 1, 2, 3, 4];
6 int[5] arr   = [0, 1, 2, 3, 4];
7 int*[]  slicep = [p];
8 int*[1] arrp   = [&i];
9 
10 // A slice points to all of its members:
11 assert( slice.doesPointTo(slice[3]));
12 assert(!slice[0 .. 2].doesPointTo(slice[3])); // Object 3 is outside of the
13                                               // slice [0 .. 2]
14 
15 // Note that a slice will not take into account what its members point to.
16 assert( slicep[0].doesPointTo(i));
17 assert(!slicep   .doesPointTo(i));
18 
19 // static arrays are objects that own their members, just like structs:
20 assert(!arr.doesPointTo(arr[0])); // arr[0] is just a member of arr, so not
21                                   // pointed.
22 assert( arrp[0].doesPointTo(i));  // i is pointed by arrp[0].
23 assert( arrp   .doesPointTo(i));  // which means i is pointed by arrp
24                                   // itself.
25 
26 // Notice the difference between static and dynamic arrays:
27 assert(!arr  .doesPointTo(arr[0]));
28 assert( arr[].doesPointTo(arr[0]));
29 assert( arrp  .doesPointTo(i));
30 assert(!arrp[].doesPointTo(i));

Classes

1 class C
2 {
3     this(int* p){this.p = p;}
4     int* p;
5 }
6 int i;
7 C a = new C(&i);
8 C b = a;
9 
10 // Classes are a bit particular, as they are treated like simple pointers
11 // to a class payload.
12 assert( a.p.doesPointTo(i)); // a.p points to i.
13 assert(!a  .doesPointTo(i)); // Yet a itself does not point i.
14 
15 //To check the class payload itself, iterate on its members:
16 ()
17 {
18     import std.traits : Fields;
19 
20     foreach (index, _; Fields!C)
21         if (doesPointTo(a.tupleof[index], i))
22             return;
23     assert(0);
24 }();
25 
26 // To check if a class points a specific payload, a direct memmory check
27 // can be done:
28 auto aLoc = cast(ubyte[__traits(classInstanceSize, C)]*) a;
29 assert(b.doesPointTo(*aLoc)); // b points to where a is pointing

Meta

Suggestion Box / Bug Report