1 static assert( isImplicitlyConvertible!(byte, long)); 2 static assert( isImplicitlyConvertible!(ushort, long)); 3 static assert( isImplicitlyConvertible!(int, long)); 4 static assert( isImplicitlyConvertible!(long, long)); 5 static assert( isImplicitlyConvertible!(ulong, long)); 6 7 static assert( isImplicitlyConvertible!(ubyte, int)); 8 static assert( isImplicitlyConvertible!(short, int)); 9 static assert( isImplicitlyConvertible!(int, int)); 10 static assert( isImplicitlyConvertible!(uint, int)); 11 static assert(!isImplicitlyConvertible!(long, int)); 12 static assert(!isImplicitlyConvertible!(ulong, int)); 13 14 static assert(!isImplicitlyConvertible!(int, string)); 15 static assert(!isImplicitlyConvertible!(int, int[])); 16 static assert(!isImplicitlyConvertible!(int, int*)); 17 18 static assert(!isImplicitlyConvertible!(string, int)); 19 static assert(!isImplicitlyConvertible!(int[], int)); 20 static assert(!isImplicitlyConvertible!(int*, int)); 21 22 // For better or worse, bool and the built-in character types will 23 // implicitly convert to integer or floating-point types if the target type 24 // is large enough. Sometimes, this is desirable, whereas at other times, 25 // it can have very surprising results, so it's one reason why code should 26 // be very careful when testing for implicit conversions. 27 static assert( isImplicitlyConvertible!(bool, int)); 28 static assert( isImplicitlyConvertible!(char, int)); 29 static assert( isImplicitlyConvertible!(wchar, int)); 30 static assert( isImplicitlyConvertible!(dchar, int)); 31 32 static assert( isImplicitlyConvertible!(bool, ubyte)); 33 static assert( isImplicitlyConvertible!(char, ubyte)); 34 static assert(!isImplicitlyConvertible!(wchar, ubyte)); 35 static assert(!isImplicitlyConvertible!(dchar, ubyte)); 36 37 static assert( isImplicitlyConvertible!(bool, double)); 38 static assert( isImplicitlyConvertible!(char, double)); 39 static assert( isImplicitlyConvertible!(wchar, double)); 40 static assert( isImplicitlyConvertible!(dchar, double)); 41 42 // Value types can be implicitly converted regardless of their qualifiers 43 // thanks to the fact that they're copied. 44 static assert( isImplicitlyConvertible!(int, int)); 45 static assert( isImplicitlyConvertible!(const int, int)); 46 static assert( isImplicitlyConvertible!(immutable int, int)); 47 static assert( isImplicitlyConvertible!(inout int, int)); 48 49 static assert( isImplicitlyConvertible!(int, const int)); 50 static assert( isImplicitlyConvertible!(int, immutable int)); 51 static assert( isImplicitlyConvertible!(int, inout int)); 52 53 // Reference types are far more restrictive about which implicit conversions 54 // they allow, because qualifiers in D are transitive. 55 static assert( isImplicitlyConvertible!(int*, int*)); 56 static assert(!isImplicitlyConvertible!(const int*, int*)); 57 static assert(!isImplicitlyConvertible!(immutable int*, int*)); 58 59 static assert( isImplicitlyConvertible!(int*, const int*)); 60 static assert( isImplicitlyConvertible!(const int*, const int*)); 61 static assert( isImplicitlyConvertible!(immutable int*, const int*)); 62 63 static assert(!isImplicitlyConvertible!(int*, immutable int*)); 64 static assert(!isImplicitlyConvertible!(const int*, immutable int*)); 65 static assert( isImplicitlyConvertible!(immutable int*, immutable int*)); 66 67 // Note that inout gets a bit weird, since it's only used with function 68 // parameters, and it's a stand-in for whatever mutability qualifiers the 69 // type actually has. So, a function parameter that's inout accepts any 70 // mutability, but you can't actually implicitly convert to inout, because 71 // it's unknown within the function what the actual mutability of the type 72 // is. It will differ depending on the function arguments of a specific 73 // call to that function, so the same code has to work with all combinations 74 // of mutability qualifiers. 75 static assert(!isImplicitlyConvertible!(int*, inout int*)); 76 static assert(!isImplicitlyConvertible!(const int*, inout int*)); 77 static assert(!isImplicitlyConvertible!(immutable int*, inout int*)); 78 static assert( isImplicitlyConvertible!(inout int*, inout int*)); 79 80 static assert(!isImplicitlyConvertible!(inout int*, int*)); 81 static assert( isImplicitlyConvertible!(inout int*, const int*)); 82 static assert(!isImplicitlyConvertible!(inout int*, immutable int*)); 83 84 // Enums implicitly convert to their base type. 85 enum E : int 86 { 87 a = 42 88 } 89 static assert( isImplicitlyConvertible!(E, int)); 90 static assert( isImplicitlyConvertible!(E, long)); 91 static assert(!isImplicitlyConvertible!(E, int[])); 92 93 // Structs only implicit convert to another type via declaring an 94 // alias this. 95 static struct S 96 { 97 int i; 98 } 99 static assert(!isImplicitlyConvertible!(S, int)); 100 static assert(!isImplicitlyConvertible!(S, long)); 101 static assert(!isImplicitlyConvertible!(S, string)); 102 103 static struct AliasThis 104 { 105 int i; 106 alias this = i; 107 } 108 static assert( isImplicitlyConvertible!(AliasThis, int)); 109 static assert( isImplicitlyConvertible!(AliasThis, long)); 110 static assert(!isImplicitlyConvertible!(AliasThis, string)); 111 112 static struct AliasThis2 113 { 114 AliasThis at; 115 alias this = at; 116 } 117 static assert( isImplicitlyConvertible!(AliasThis2, AliasThis)); 118 static assert( isImplicitlyConvertible!(AliasThis2, int)); 119 static assert( isImplicitlyConvertible!(AliasThis2, long)); 120 static assert(!isImplicitlyConvertible!(AliasThis2, string)); 121 122 static struct AliasThis3 123 { 124 AliasThis2 at; 125 alias this = at; 126 } 127 static assert( isImplicitlyConvertible!(AliasThis3, AliasThis2)); 128 static assert( isImplicitlyConvertible!(AliasThis3, AliasThis)); 129 static assert( isImplicitlyConvertible!(AliasThis3, int)); 130 static assert( isImplicitlyConvertible!(AliasThis3, long)); 131 static assert(!isImplicitlyConvertible!(AliasThis3, string)); 132 133 // D does not support implicit conversions via construction. 134 static struct Cons 135 { 136 this(int i) 137 { 138 this.i = i; 139 } 140 141 int i; 142 } 143 static assert(!isImplicitlyConvertible!(int, Cons)); 144 145 // Classes support implicit conversion based on their class and 146 // interface hierarchies. 147 static interface I1 {} 148 static class Base : I1 {} 149 150 static interface I2 {} 151 static class Foo : Base, I2 {} 152 153 static class Bar : Base {} 154 155 static assert( isImplicitlyConvertible!(Base, Base)); 156 static assert(!isImplicitlyConvertible!(Base, Foo)); 157 static assert(!isImplicitlyConvertible!(Base, Bar)); 158 static assert( isImplicitlyConvertible!(Base, I1)); 159 static assert(!isImplicitlyConvertible!(Base, I2)); 160 161 static assert( isImplicitlyConvertible!(Foo, Base)); 162 static assert( isImplicitlyConvertible!(Foo, Foo)); 163 static assert(!isImplicitlyConvertible!(Foo, Bar)); 164 static assert( isImplicitlyConvertible!(Foo, I1)); 165 static assert( isImplicitlyConvertible!(Foo, I2)); 166 167 static assert( isImplicitlyConvertible!(Bar, Base)); 168 static assert(!isImplicitlyConvertible!(Bar, Foo)); 169 static assert( isImplicitlyConvertible!(Bar, Bar)); 170 static assert( isImplicitlyConvertible!(Bar, I1)); 171 static assert(!isImplicitlyConvertible!(Bar, I2)); 172 173 static assert(!isImplicitlyConvertible!(I1, Base)); 174 static assert(!isImplicitlyConvertible!(I1, Foo)); 175 static assert(!isImplicitlyConvertible!(I1, Bar)); 176 static assert( isImplicitlyConvertible!(I1, I1)); 177 static assert(!isImplicitlyConvertible!(I1, I2)); 178 179 static assert(!isImplicitlyConvertible!(I2, Base)); 180 static assert(!isImplicitlyConvertible!(I2, Foo)); 181 static assert(!isImplicitlyConvertible!(I2, Bar)); 182 static assert(!isImplicitlyConvertible!(I2, I1)); 183 static assert( isImplicitlyConvertible!(I2, I2)); 184 185 // Note that arrays are not implicitly convertible even when their elements 186 // are implicitly convertible. 187 static assert(!isImplicitlyConvertible!(ubyte[], uint[])); 188 static assert(!isImplicitlyConvertible!(Foo[], Base[])); 189 static assert(!isImplicitlyConvertible!(Bar[], Base[])); 190 191 // However, like with pointers, dynamic arrays are convertible based on 192 // constness. 193 static assert( isImplicitlyConvertible!(Base[], const Base[])); 194 static assert( isImplicitlyConvertible!(Base[], const(Base)[])); 195 static assert(!isImplicitlyConvertible!(Base[], immutable(Base)[])); 196 static assert(!isImplicitlyConvertible!(const Base[], immutable Base[])); 197 static assert( isImplicitlyConvertible!(const Base[], const Base[])); 198 static assert(!isImplicitlyConvertible!(const Base[], immutable Base[]));
isImplicitlyConvertible can be used with partial instantiation so that it can be passed to a template which takes a unary predicate.
import phobos.sys.meta : AliasSeq, all, indexOf; // byte is implicitly convertible to byte, short, int, and long. static assert(all!(isImplicitlyConvertible!byte, short, int, long)); // const(char)[] at index 2 is the first type in the AliasSeq which string // can be implicitly converted to. alias Types = AliasSeq!(int, char[], const(char)[], string, int*); static assert(indexOf!(isImplicitlyConvertible!string, Types) == 2);
Whether the type From is implicitly convertible to the type To.
Note that template constraints should be very careful about when they test for implicit conversions and in general should prefer to either test for an exact set of types or for types which compile with a particular piece of code rather than being designed to accept any type which implicitly converts to a particular type.
This is because having a type pass a template constraint based on an implicit conversion but then not have the implicit conversion actually take place (which it won't unless the template does something to force it internally) can lead to either compilation errors or subtle behavioral differences - and even when the conversion is done explicitly within a templated function, since it's not done at the call site, it can still lead to subtle bugs in some cases (e.g. if slicing a static array is involved).
For situations where code needs to verify that a type is implicitly convertible based solely on its qualifiers, isQualifierConvertible would be a more appropriate choice than isImplicitlyConvertible.
Given how trivial the is expression for isImplicitlyConvertible is - is(To : From) - this trait is provided primarily so that it can be used in conjunction with templates that use a template predicate (such as many of the templates in phobos.sys.meta).
The single-argument overload makes it so that it can be partially instantiated with the first argument, which will often be necessary with template predicates.