|
51 | 51 | $(BOOKTABLE ,
|
52 | 52 | $(TR $(TH Category) $(TH Templates))
|
53 | 53 | $(TR $(TD Categories of types) $(TD
|
| 54 | + $(LREF isAggregateType) |
54 | 55 | $(LREF isDynamicArray)
|
55 | 56 | $(LREF isFloatingPoint)
|
| 57 | + $(LREF isInstantiationOf) |
56 | 58 | $(LREF isInteger)
|
57 | 59 | $(LREF isNumeric)
|
58 | 60 | $(LREF isPointer)
|
|
109 | 111 | +/
|
110 | 112 | module phobos.sys.traits;
|
111 | 113 |
|
| 114 | +/++ |
| 115 | + Whether the given type is an "aggregate type" - i.e. a struct, class, |
| 116 | + interface, or union. |
| 117 | + +/ |
| 118 | +enum isAggregateType(T) = is(T == struct) || is(T == class) || is(T == interface) || is(T == union); |
| 119 | + |
| 120 | +@safe unittest |
| 121 | +{ |
| 122 | + struct S {} |
| 123 | + class C {} |
| 124 | + interface I {} |
| 125 | + union U {} |
| 126 | + |
| 127 | + static assert( isAggregateType!S); |
| 128 | + static assert( isAggregateType!C); |
| 129 | + static assert( isAggregateType!I); |
| 130 | + static assert( isAggregateType!U); |
| 131 | + static assert( isAggregateType!(const S)); |
| 132 | + static assert( isAggregateType!(shared C)); |
| 133 | + |
| 134 | + static assert(!isAggregateType!int); |
| 135 | + static assert(!isAggregateType!string); |
| 136 | + static assert(!isAggregateType!(S*)); |
| 137 | + static assert(!isAggregateType!(C[])); |
| 138 | + static assert(!isAggregateType!(I[string])); |
| 139 | +} |
| 140 | + |
112 | 141 | /++
|
113 | 142 | Whether the given type is a dynamic array (or what is sometimes referred to
|
114 | 143 | as a slice, since a dynamic array in D is a slice of memory).
|
@@ -1309,6 +1338,239 @@ enum isPointer(T) = is(T == U*, U);
|
1309 | 1338 | }
|
1310 | 1339 | }
|
1311 | 1340 |
|
| 1341 | +/++ |
| 1342 | + Evaluates to $(D true) if the given type or symbol is an instantiation of |
| 1343 | + the given template. |
| 1344 | +
|
| 1345 | + The overload which takes $(D T) operates on types and indicates whether an |
| 1346 | + aggregate type (i.e. struct, class, interface, or union) is an |
| 1347 | + instantiation of the given template. |
| 1348 | +
|
| 1349 | + The overload which takes $(D Symbol) operates on function templates, |
| 1350 | + because unlike with aggregate types, the type of a function does not retain |
| 1351 | + the fact that it was instantiated from a template. So, for functions, it's |
| 1352 | + necessary to pass the function itself as a symbol rather than pass the type |
| 1353 | + of the function. |
| 1354 | +
|
| 1355 | + The overload which takes $(D Symbol) also works with templates which are |
| 1356 | + not types or functions. |
| 1357 | +
|
| 1358 | + The single-argument overload makes it so that it can be partially |
| 1359 | + instantiated with the first argument, which will often be necessary with |
| 1360 | + template predicates. |
| 1361 | + +/ |
| 1362 | +template isInstantiationOf(alias Template, T) |
| 1363 | +if (__traits(isTemplate, Template)) |
| 1364 | +{ |
| 1365 | + enum isInstantiationOf = is(T == Template!Args, Args...); |
| 1366 | +} |
| 1367 | + |
| 1368 | +/++ Ditto +/ |
| 1369 | +template isInstantiationOf(alias Template, alias Symbol) |
| 1370 | +if (__traits(isTemplate, Template)) |
| 1371 | +{ |
| 1372 | + enum impl(alias T : Template!Args, Args...) = true; |
| 1373 | + enum impl(alias T) = false; |
| 1374 | + enum isInstantiationOf = impl!Symbol; |
| 1375 | +} |
| 1376 | + |
| 1377 | +/++ Ditto +/ |
| 1378 | +template isInstantiationOf(alias Template) |
| 1379 | +if (__traits(isTemplate, Template)) |
| 1380 | +{ |
| 1381 | + enum isInstantiationOf(T) = is(T == Template!Args, Args...); |
| 1382 | + |
| 1383 | + template isInstantiationOf(alias Symbol) |
| 1384 | + { |
| 1385 | + enum impl(alias T : Template!Args, Args...) = true; |
| 1386 | + enum impl(alias T) = false; |
| 1387 | + enum isInstantiationOf = impl!Symbol; |
| 1388 | + } |
| 1389 | +} |
| 1390 | + |
| 1391 | +/// Examples of templated types. |
| 1392 | +@safe unittest |
| 1393 | +{ |
| 1394 | + static struct S(T) {} |
| 1395 | + static class C(T) {} |
| 1396 | + |
| 1397 | + static assert( isInstantiationOf!(S, S!int)); |
| 1398 | + static assert( isInstantiationOf!(S, S!int)); |
| 1399 | + static assert( isInstantiationOf!(S, S!string)); |
| 1400 | + static assert( isInstantiationOf!(S, const S!string)); |
| 1401 | + static assert( isInstantiationOf!(S, shared S!string)); |
| 1402 | + static assert(!isInstantiationOf!(S, int)); |
| 1403 | + static assert(!isInstantiationOf!(S, C!int)); |
| 1404 | + static assert(!isInstantiationOf!(S, C!string)); |
| 1405 | + static assert(!isInstantiationOf!(S, C!(S!int))); |
| 1406 | + |
| 1407 | + static assert( isInstantiationOf!(C, C!int)); |
| 1408 | + static assert( isInstantiationOf!(C, C!string)); |
| 1409 | + static assert( isInstantiationOf!(C, const C!string)); |
| 1410 | + static assert( isInstantiationOf!(C, shared C!string)); |
| 1411 | + static assert(!isInstantiationOf!(C, int)); |
| 1412 | + static assert(!isInstantiationOf!(C, S!int)); |
| 1413 | + static assert(!isInstantiationOf!(C, S!string)); |
| 1414 | + static assert(!isInstantiationOf!(C, S!(C!int))); |
| 1415 | + |
| 1416 | + static struct Variadic(T...) {} |
| 1417 | + |
| 1418 | + static assert( isInstantiationOf!(Variadic, Variadic!())); |
| 1419 | + static assert( isInstantiationOf!(Variadic, Variadic!int)); |
| 1420 | + static assert( isInstantiationOf!(Variadic, Variadic!(int, string))); |
| 1421 | + static assert( isInstantiationOf!(Variadic, Variadic!(int, string, int))); |
| 1422 | + static assert( isInstantiationOf!(Variadic, const Variadic!(int, short))); |
| 1423 | + static assert( isInstantiationOf!(Variadic, shared Variadic!(int, short))); |
| 1424 | + static assert(!isInstantiationOf!(Variadic, int)); |
| 1425 | + static assert(!isInstantiationOf!(Variadic, S!int)); |
| 1426 | + static assert(!isInstantiationOf!(Variadic, C!int)); |
| 1427 | + |
| 1428 | + static struct ValueArg(int i) {} |
| 1429 | + static assert( isInstantiationOf!(ValueArg, ValueArg!42)); |
| 1430 | + static assert( isInstantiationOf!(ValueArg, ValueArg!256)); |
| 1431 | + static assert( isInstantiationOf!(ValueArg, const ValueArg!1024)); |
| 1432 | + static assert( isInstantiationOf!(ValueArg, shared ValueArg!1024)); |
| 1433 | + static assert(!isInstantiationOf!(ValueArg, int)); |
| 1434 | + static assert(!isInstantiationOf!(ValueArg, S!int)); |
| 1435 | + |
| 1436 | + int i; |
| 1437 | + |
| 1438 | + static struct AliasArg(alias Symbol) {} |
| 1439 | + static assert( isInstantiationOf!(AliasArg, AliasArg!42)); |
| 1440 | + static assert( isInstantiationOf!(AliasArg, AliasArg!int)); |
| 1441 | + static assert( isInstantiationOf!(AliasArg, AliasArg!i)); |
| 1442 | + static assert( isInstantiationOf!(AliasArg, const AliasArg!i)); |
| 1443 | + static assert( isInstantiationOf!(AliasArg, shared AliasArg!i)); |
| 1444 | + static assert(!isInstantiationOf!(AliasArg, int)); |
| 1445 | + static assert(!isInstantiationOf!(AliasArg, S!int)); |
| 1446 | + |
| 1447 | + // An uninstantiated template is not an instance of any template, |
| 1448 | + // not even itself. |
| 1449 | + static assert(!isInstantiationOf!(S, S)); |
| 1450 | + static assert(!isInstantiationOf!(S, C)); |
| 1451 | + static assert(!isInstantiationOf!(C, C)); |
| 1452 | + static assert(!isInstantiationOf!(C, S)); |
| 1453 | + |
| 1454 | + // Variables of a templated type are not considered instantiations of that |
| 1455 | + // type. For templated types, the overload which takes a type must be used. |
| 1456 | + S!int s; |
| 1457 | + C!string c; |
| 1458 | + static assert(!isInstantiationOf!(S, s)); |
| 1459 | + static assert(!isInstantiationOf!(C, c)); |
| 1460 | +} |
| 1461 | + |
| 1462 | +// Examples of templated functions. |
| 1463 | +@safe unittest |
| 1464 | +{ |
| 1465 | + static int foo(T...)() { return 42; } |
| 1466 | + static void bar(T...)(T var) {} |
| 1467 | + static void baz(T)(T var) {} |
| 1468 | + static bool frobozz(alias pred)(int) { return true; } |
| 1469 | + |
| 1470 | + static assert( isInstantiationOf!(foo, foo!int)); |
| 1471 | + static assert( isInstantiationOf!(foo, foo!string)); |
| 1472 | + static assert( isInstantiationOf!(foo, foo!(int, string))); |
| 1473 | + static assert(!isInstantiationOf!(foo, bar!int)); |
| 1474 | + static assert(!isInstantiationOf!(foo, bar!string)); |
| 1475 | + static assert(!isInstantiationOf!(foo, bar!(int, string))); |
| 1476 | + |
| 1477 | + static assert( isInstantiationOf!(bar, bar!int)); |
| 1478 | + static assert( isInstantiationOf!(bar, bar!string)); |
| 1479 | + static assert( isInstantiationOf!(bar, bar!(int, string))); |
| 1480 | + static assert(!isInstantiationOf!(bar, foo!int)); |
| 1481 | + static assert(!isInstantiationOf!(bar, foo!string)); |
| 1482 | + static assert(!isInstantiationOf!(bar, foo!(int, string))); |
| 1483 | + |
| 1484 | + static assert( isInstantiationOf!(baz, baz!int)); |
| 1485 | + static assert( isInstantiationOf!(baz, baz!string)); |
| 1486 | + static assert(!isInstantiationOf!(baz, foo!(int, string))); |
| 1487 | + |
| 1488 | + static assert( isInstantiationOf!(frobozz, frobozz!(a => a))); |
| 1489 | + static assert( isInstantiationOf!(frobozz, frobozz!(a => a > 2))); |
| 1490 | + static assert(!isInstantiationOf!(frobozz, baz!int)); |
| 1491 | + |
| 1492 | + // Unfortunately, the function type is not considered an instantiation of |
| 1493 | + // the template, because that information is not part of the type, unlike |
| 1494 | + // with templated structs or classes. |
| 1495 | + static assert(!isInstantiationOf!(foo, typeof(foo!int))); |
| 1496 | + static assert(!isInstantiationOf!(bar, typeof(bar!int))); |
| 1497 | +} |
| 1498 | + |
| 1499 | +// Examples of templates which aren't types or functions. |
| 1500 | +@safe unittest |
| 1501 | +{ |
| 1502 | + template SingleArg(T) {} |
| 1503 | + template Variadic(T...) {} |
| 1504 | + template ValueArg(string s) {} |
| 1505 | + template Alias(alias symbol) {} |
| 1506 | + |
| 1507 | + static assert( isInstantiationOf!(SingleArg, SingleArg!int)); |
| 1508 | + static assert( isInstantiationOf!(SingleArg, SingleArg!string)); |
| 1509 | + static assert(!isInstantiationOf!(SingleArg, int)); |
| 1510 | + static assert(!isInstantiationOf!(SingleArg, Variadic!int)); |
| 1511 | + |
| 1512 | + static assert( isInstantiationOf!(Variadic, Variadic!())); |
| 1513 | + static assert( isInstantiationOf!(Variadic, Variadic!int)); |
| 1514 | + static assert( isInstantiationOf!(Variadic, Variadic!string)); |
| 1515 | + static assert( isInstantiationOf!(Variadic, Variadic!(short, int, long))); |
| 1516 | + static assert(!isInstantiationOf!(Variadic, int)); |
| 1517 | + static assert(!isInstantiationOf!(Variadic, SingleArg!int)); |
| 1518 | + |
| 1519 | + static assert( isInstantiationOf!(ValueArg, ValueArg!"dlang")); |
| 1520 | + static assert( isInstantiationOf!(ValueArg, ValueArg!"foobar")); |
| 1521 | + static assert(!isInstantiationOf!(ValueArg, string)); |
| 1522 | + static assert(!isInstantiationOf!(ValueArg, Variadic!string)); |
| 1523 | + |
| 1524 | + int i; |
| 1525 | + |
| 1526 | + static assert( isInstantiationOf!(Alias, Alias!int)); |
| 1527 | + static assert( isInstantiationOf!(Alias, Alias!42)); |
| 1528 | + static assert( isInstantiationOf!(Alias, Alias!i)); |
| 1529 | + static assert(!isInstantiationOf!(Alias, int)); |
| 1530 | + static assert(!isInstantiationOf!(Alias, SingleArg!int)); |
| 1531 | +} |
| 1532 | + |
| 1533 | +/// Examples of partial instantation. |
| 1534 | +@safe unittest |
| 1535 | +{ |
| 1536 | + static struct SingleArg(T) {} |
| 1537 | + static struct Variadic(T...) {} |
| 1538 | + |
| 1539 | + alias isSingleArg = isInstantiationOf!SingleArg; |
| 1540 | + alias isVariadic = isInstantiationOf!Variadic; |
| 1541 | + |
| 1542 | + static assert( isSingleArg!(SingleArg!int)); |
| 1543 | + static assert( isSingleArg!(const SingleArg!int)); |
| 1544 | + static assert(!isSingleArg!int); |
| 1545 | + static assert(!isSingleArg!(Variadic!int)); |
| 1546 | + |
| 1547 | + static assert( isVariadic!(Variadic!())); |
| 1548 | + static assert( isVariadic!(Variadic!int)); |
| 1549 | + static assert( isVariadic!(shared Variadic!int)); |
| 1550 | + static assert( isVariadic!(Variadic!(int, string))); |
| 1551 | + static assert(!isVariadic!int); |
| 1552 | + static assert(!isVariadic!(SingleArg!int)); |
| 1553 | + |
| 1554 | + T foo(T)(T t) { return t; } |
| 1555 | + T likeFoo(T)(T t) { return t; } |
| 1556 | + bool bar(alias pred)(int i) { return pred(i); } |
| 1557 | + |
| 1558 | + alias isFoo = isInstantiationOf!foo; |
| 1559 | + alias isBar = isInstantiationOf!bar; |
| 1560 | + |
| 1561 | + static assert( isFoo!(foo!int)); |
| 1562 | + static assert( isFoo!(foo!string)); |
| 1563 | + static assert(!isFoo!int); |
| 1564 | + static assert(!isFoo!(likeFoo!int)); |
| 1565 | + static assert(!isFoo!(bar!(a => true))); |
| 1566 | + |
| 1567 | + static assert( isBar!(bar!(a => true))); |
| 1568 | + static assert( isBar!(bar!(a => a > 2))); |
| 1569 | + static assert(!isBar!int); |
| 1570 | + static assert(!isBar!(foo!int)); |
| 1571 | + static assert(!isBar!(likeFoo!int)); |
| 1572 | +} |
| 1573 | + |
1312 | 1574 | /++
|
1313 | 1575 | Evaluates to an $(D AliasSeq) containing the members of an enum type.
|
1314 | 1576 |
|
|
0 commit comments