std.experimental.typecons - D Programming Language
Description: D Programming Language
Keywords: D programming language

Menu

- Learn
- Documentation
  - Language Reference
  - Library Reference
  - Command-line Reference
  - Feature Overview
  - Articles
- Downloads
- Packages
- Community
  - Blog
  - Orgs using D
  - Twitter
  - Calendar
  - Forums
  - IRC
  - Community Discord
  - Wiki
  - GitHub
  - Issues
  - Get involved
  - Contributors
  - Foundation
  - Security Team
  - Donate
  - Sponsors
- Resources
  - Tour
  - Books
  - Tutorials
  - Tools
  - Editors
  - IDEs
  - run.dlang.io
  - Visual D
  - Acknowledgments
  - D Style
  - Glossary
  - Sitemap

Search
Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

# std.experimental.typecons

This module implements experimental additions/modifications to std.typecons.
Use this module to test out new functionality for std.typecons.wrap which allows for a struct to be wrapped against an interface; the implementation in std.typecons only allows for classes to use the wrap functionality.

Source std/experimental/typecons.d

License:
Boost License 1.0.
Authors:
Andrei Alexandrescu, Bartosz Milewski, Don Clugston, Shin Fujishiro, Kenji Hara

template `wrap`(Targets...) if (Targets.length >= 1 && allSatisfy!(isInterface, Targets))
  auto `wrap`(Source)(inout Source `src`)
  if (implementsInterface!(Source, Targets));
    Wrap src in an anonymous class implementing Targets.
    wrap creates an internal wrapper class which implements the interfaces in Targets using the methods of `src`, then returns a GC-allocated instance of it.
    Source can be either a class or a struct, but it must structurally conform with all the Targets interfaces; i.e. it must provide concrete methods with compatible signatures of those in Targets.
    If Source is a struct then wrapping/unwrapping will create a copy; it is not possible to affect the original struct through the wrapper.
    The returned object additionally supports unwrap.

    Note If Targets has only one entry and Source is a class which explicitly implements it, wrap simply returns src upcasted to Targets[0].

    Bugs:
    wrap does not support interfaces which take their own type as either a parameter type or return type in any of its methods.
    See Also:
    unwrap for examples
inout(Target) `unwrap`(Target, Source)(inout Source `src`);
  Extract object previously wrapped by wrap.
  Parameters:

  Target | type of wrapped object
  Source `src` | wrapper object returned by wrap

  Returns:
  the wrapped object, or null if src is not a wrapper created by wrap and Target is a class
  Throws:
  std.conv.ConvException when attempting to extract a struct which is not the wrapped type
  See Also:
  wrap
  Examples:

      interface Quack
      {
          int quack();
          @property int height();
      }
      interface Flyer
      {
          @property int height();
      }
      class Duck : Quack
      {
          int quack() { return 1; }
          @property int height() { return 10; }
      }
      class Human
      {
          int quack() { return 2; }
          @property int height() { return 20; }
      }
      struct HumanStructure
      {
          int quack() { return 3; }
          @property int height() { return 30; }
      }

      Duck d1 = new Duck();
      Human h1 = new Human();
      HumanStructure hs1;

      interface Refreshable
      {
          int refresh();
      }
      // does not have structural conformance
      static assert(!__traits(compiles, d1.wrap!Refreshable));
      static assert(!__traits(compiles, h1.wrap!Refreshable));
      static assert(!__traits(compiles, hs1.wrap!Refreshable));

      // strict upcast
      Quack qd = d1.wrap!Quack;
      assert(qd is d1);
      assert(qd.quack() == 1);    // calls Duck.quack
      // strict downcast
      Duck d2 = qd.unwrap!Duck;
      assert(d2 is d1);

      // structural upcast
      Quack qh = h1.wrap!Quack;
      Quack qhs = hs1.wrap!Quack;
      assert(qh.quack() == 2);    // calls Human.quack
      assert(qhs.quack() == 3);    // calls HumanStructure.quack
      // structural downcast
      Human h2 = qh.unwrap!Human;
      HumanStructure hs2 = qhs.unwrap!HumanStructure;
      assert(h2 is h1);
      assert(hs2 is hs1);

      // structural upcast (two steps)
      Quack qx = h1.wrap!Quack;   // Human -> Quack
      Quack qxs = hs1.wrap!Quack;   // HumanStructure -> Quack
      Flyer fx = qx.wrap!Flyer;   // Quack -> Flyer
      Flyer fxs = qxs.wrap!Flyer;   // Quack -> Flyer
      assert(fx.height == 20);    // calls Human.height
      assert(fxs.height == 30);    // calls HumanStructure.height
      // strucural downcast (two steps)
      Quack qy = fx.unwrap!Quack; // Flyer -> Quack
      Quack qys = fxs.unwrap!Quack; // Flyer -> Quack
      Human hy = qy.unwrap!Human; // Quack -> Human
      HumanStructure hys = qys.unwrap!HumanStructure; // Quack -> HumanStructure
      assert(hy is h1);
      assert(hys is hs1);
      // strucural downcast (one step)
      Human hz = fx.unwrap!Human; // Flyer -> Human
      HumanStructure hzs = fxs.unwrap!HumanStructure; // Flyer -> HumanStructure
      assert(hz is h1);
      assert(hzs is hs1);

  Examples:

      import std.traits : functionAttributes, FunctionAttribute;
      interface A { int run(); }
      interface B { int stop(); @property int status(); }
      class X
      {
          int run() { return 1; }
          int stop() { return 2; }
          @property int status() { return 3; }
      }

      auto x = new X();
      auto ab = x.wrap!(A, B);
      A a = ab;
      B b = ab;
      writeln(a.run()); // 1
      writeln(b.stop()); // 2
      writeln(b.status); // 3
      static assert(functionAttributes!(typeof(ab).status) & FunctionAttribute.property);

template `Final`(T)
Final!T `makeFinal`(T)(T `t`);
  Type constructor for final (aka head-const) variables.
  Final variables cannot be directly mutated or rebound, but references reached through the variable are typed with their original mutability. It is equivalent to final variables in D1 and Java, as well as readonly variables in C#.
  When T is a const or immutable type, `Final` aliases to T.
  Examples:
  `Final` can be used to create class references which cannot be rebound:

      static class A
      {
          int i;

          this(int i) pure nothrow @nogc @safe
          {
              this.i = i;
          }
      }

      auto a = makeFinal(new A(42));
      writeln(a.i); // 42

      //a = new A(24); // Reassignment is illegal,
      a.i = 24; // But fields are still mutable.

      writeln(a.i); // 24

  Examples:
  `Final` can also be used to create read-only data fields without using transitive immutability:

      static class A
      {
          int i;

          this(int i) pure nothrow @nogc @safe
          {
              this.i = i;
          }
      }

      static class B
      {
          Final!A a;

          this(A a) pure nothrow @nogc @safe
          {
              this.a = a; // Construction, thus allowed.
          }
      }

      auto b = new B(new A(42));
      writeln(b.a.i); // 42

      // b.a = new A(24); // Reassignment is illegal,
      b.a.i = 24; // but `a` is still mutable.

      writeln(b.a.i); // 24

Copyright © 1999-2021 by the D Language Foundation | Page generated by Ddoc on Fri Apr 23 18:59:13 2021