"__traits(getMember,...)" should always work, whatever is the member protection (as long as the symbol is a valid one).
The current limitation is problematic because it prevents to write functions related to traits in a separate dedicated modules (e.g mylib.traits)
Every time a "__traits(getMember,...)" has to be used the only solution to make it works with a private member is to write again and again the code (or to warp the function in a mixin template).
Since there is also the traits verb "getProtection", it still would be possible to respect the protection or not.
In case this wouldn't be clear, more concretly:
======================================
module mylib.traits;
mixin template ScopedReachability()
{
bool isMemberReachableGood(T, string member)()
if (is(T==class) || is(T==struct))
{
return __traits(compiles, __traits(getMember, T, member));
}
}
bool isMemberReachableBad(T, string member)()
if (is(T==class) || is(T==struct))
{
return __traits(compiles, __traits(getMember, T, member));
}
=====================================
module somemodule;
class Foo
{
private:
uint a,b,c;
public:
this()
{
foreach(member; __traits(allMembers, Foo))
static if (isMemberReachableBad!(Foo, member)) {/*a,b,c not detected*/}
import mylib.traits;
mixin ScopedReachability; // isMemberReachableGood is now a local func.
static if (isMemberReachableGood!(Foo, member)) {/*a,b,c detected*/}
}
}
=====================================
With a relaxed protection policy on the "getMember" verb, it would be possible to write reusable functions related to traits. Actually the problem prevents a lot of good template that would simplify the traits usage to be written.
=====================================
see also:
- https://issues.dlang.org/show_bug.cgi?id=15335
- http://forum.dlang.org/post/[email protected]
Also if a template would be instantiated in the module that use it...
Comment #4 by b2.temp — 2016-05-31T20:54:59Z
In the meantime, when the trait code is for a struct or a class it's possible to use its '.tupleof' property. It's not affected by the visibility.
Instead of all member:
import std.meta: aliasSeqOf;
import std.range: iota;
foreach(i; aliasSeqOf!(iota(0, T.tupleof.length)))
{
alias MT = typeof(T.tupleof[i]);
...
}
This is not exactly the same but when the trait code is to inspect the variable types or UDAs it works fine.
Comment #5 by doob — 2016-06-01T06:48:12Z
A pointer can be used as well to bypass the protection. It works for other symbols than fields.
Comment #6 by code — 2016-08-12T11:33:58Z
(In reply to b2.temp from comment #3)
> Also if a template would be instantiated in the module that use it...
Well, there are plenty of reasons to not do that, foremost being that template instantiations should be independent of instantiation scope.
That's why we have mixin template as an alternative.
@RazvanN7 created dlang/dmd pull request #9585 "Fix Issue 15371 - __traits(getMember) should bypass the protection" fixing this issue:
- Fix Issue 15371 - __traits(getMember) should bypass the protection
https://github.com/dlang/dmd/pull/9585
Comment #10 by dlang-bot — 2019-04-12T12:10:20Z
dlang/dmd pull request #9585 "Fix Issue 15371 - __traits(getMember) should bypass the protection" was merged into master:
- bd44bc789d98baf85d2b07cf6858c573c9becccc by RazvanN7:
Fix Issue 15371 - __traits(getMember) should bypass the protection
https://github.com/dlang/dmd/pull/9585
Comment #11 by dlang-bot — 2021-01-17T23:12:06Z
dlang/dmd pull request #12135 "[dmd-cxx] Fix Issue 15371 - __traits(getMember) should bypass the protection" was merged into dmd-cxx:
- 286cb9c2f46610bc3874301dae9264f28939051f by Iain Buclaw:
[dmd-cxx] Fix Issue 15371 - __traits(getMember) should bypass the protection
https://github.com/dlang/dmd/pull/12135