|
68 | 68 | $(LREF isQualifierConvertible)
|
69 | 69 | ))
|
70 | 70 | $(TR $(TD Traits for comparisons) $(TD
|
71 |
| - $(LREF isEqual) |
72 |
| - $(LREF isSameSymbol) |
73 |
| - $(LREF isSameType) |
| 71 | + $(LREF isEqual) |
| 72 | + $(LREF isSameSymbol) |
| 73 | + $(LREF isSameType) |
74 | 74 | ))
|
75 | 75 | $(TR $(TD Traits for removing type qualfiers) $(TD
|
76 | 76 | $(LREF Unconst)
|
77 | 77 | $(LREF Unshared)
|
78 | 78 | $(LREF Unqualified)
|
79 | 79 | ))
|
80 | 80 | $(TR $(TD Type Constructors) $(TD
|
81 |
| - $(LREF ConstOf) |
82 |
| - $(LREF ImmutableOf) |
83 |
| - $(LREF InoutOf) |
84 |
| - $(LREF SharedOf) |
| 81 | + $(LREF ConstOf) |
| 82 | + $(LREF ImmutableOf) |
| 83 | + $(LREF InoutOf) |
| 84 | + $(LREF SharedOf) |
| 85 | + )) |
| 86 | + $(TR $(TD Misc) $(TD |
| 87 | + $(LREF lvalueOf) |
| 88 | + $(LREF rvalueOf) |
85 | 89 | ))
|
86 | 90 | )
|
87 | 91 |
|
@@ -2658,3 +2662,84 @@ alias SharedOf(T) = shared T;
|
2658 | 2662 | shared(bool*), shared(ubyte[]),
|
2659 | 2663 | shared(string), immutable(string))));
|
2660 | 2664 | }
|
| 2665 | + |
| 2666 | +// Needed for rvalueOf/lvalueOf because |
| 2667 | +// "inout on return means inout must be on a parameter as well" |
| 2668 | +private struct __InoutWorkaroundStruct {} |
| 2669 | + |
| 2670 | +/++ |
| 2671 | + Creates an lvalue or rvalue of type T to be used in conjunction with |
| 2672 | + $(D is(typeof(...))) or |
| 2673 | + $(DDSUBLINK spec/traits, compiles, $(D __traits(compiles, ...))). |
| 2674 | +
|
| 2675 | + The idea is that some traits or other forms of conditional compilation need |
| 2676 | + to verify that a particular piece of code compiles with an rvalue or an |
| 2677 | + lvalue of a specific type, and these $(D @property) functions allow you to |
| 2678 | + get an rvalue or lvalue of a specific type to use within an expression that |
| 2679 | + is then tested to see whether it compiles. |
| 2680 | +
|
| 2681 | + They're $(D @property) functions so that using $(D typeof) on them gives |
| 2682 | + the return type rather than the type of the function. |
| 2683 | +
|
| 2684 | + Note that these functions are $(I not) defined, so if they're actually used |
| 2685 | + outside of type introspection, they'll result in linker errors. They're |
| 2686 | + entirely for testing that a particular piece of code compiles with an rvalue |
| 2687 | + or lvalue of the given type. |
| 2688 | +
|
| 2689 | + The $(D __InoutWorkaroundStruct) parameter is entirely to make it so that |
| 2690 | + these work when the given type has the $(D inout) qualifier, since the |
| 2691 | + language requires that a function that returns an $(D inout) type also have |
| 2692 | + an $(D inout) type as a parameter. It should just be ignored. |
| 2693 | + +/ |
| 2694 | +@property T rvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init); |
| 2695 | + |
| 2696 | +/++ Ditto +/ |
| 2697 | +@property ref T lvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init); |
| 2698 | + |
| 2699 | +/// |
| 2700 | +@safe unittest |
| 2701 | +{ |
| 2702 | + static int foo(int); |
| 2703 | + static assert(is(typeof(foo(lvalueOf!int)) == int)); |
| 2704 | + static assert(is(typeof(foo(rvalueOf!int)) == int)); |
| 2705 | + |
| 2706 | + static bool bar(ref int); |
| 2707 | + static assert(is(typeof(bar(lvalueOf!int)) == bool)); |
| 2708 | + static assert(!is(typeof(bar(rvalueOf!int)))); |
| 2709 | + |
| 2710 | + static assert( is(typeof({ lvalueOf!int = 42; }))); |
| 2711 | + static assert(!is(typeof({ rvalueOf!int = 42; }))); |
| 2712 | + |
| 2713 | + static struct S {} |
| 2714 | + static assert( is(typeof({ lvalueOf!S = S.init; }))); |
| 2715 | + static assert(!is(typeof({ rvalueOf!S = S.init; }))); |
| 2716 | + |
| 2717 | + static struct NoAssign |
| 2718 | + { |
| 2719 | + @disable void opAssign(ref NoAssign); |
| 2720 | + } |
| 2721 | + static assert(!is(typeof({ lvalueOf!NoAssign = NoAssign.init; }))); |
| 2722 | + static assert(!is(typeof({ rvalueOf!NoAssign = NoAssign.init; }))); |
| 2723 | +} |
| 2724 | + |
| 2725 | +@system unittest |
| 2726 | +{ |
| 2727 | + import phobos.sys.meta : AliasSeq; |
| 2728 | + |
| 2729 | + void needLvalue(T)(ref T); |
| 2730 | + static struct S {} |
| 2731 | + int i; |
| 2732 | + struct Nested { void f() { ++i; } } |
| 2733 | + |
| 2734 | + static foreach (T; AliasSeq!(int, const int, immutable int, inout int, string, S, Nested, Object)) |
| 2735 | + { |
| 2736 | + static assert(!__traits(compiles, needLvalue(rvalueOf!T))); |
| 2737 | + static assert( __traits(compiles, needLvalue(lvalueOf!T))); |
| 2738 | + static assert(is(typeof(rvalueOf!T) == T)); |
| 2739 | + static assert(is(typeof(lvalueOf!T) == T)); |
| 2740 | + } |
| 2741 | + |
| 2742 | + static assert(!__traits(compiles, rvalueOf!int = 1)); |
| 2743 | + static assert( __traits(compiles, lvalueOf!byte = 127)); |
| 2744 | + static assert(!__traits(compiles, lvalueOf!byte = 128)); |
| 2745 | +} |
0 commit comments