D Programming Language 2.0

- Comments
- D
- Search
- Home

Last update Thu Sep 16 11:26:02 2010

# std.typecons

This module implements a variety of type constructors, i.e., templates that allow construction of new, useful general-purpose types.

Synopsis:

    // value tuples
    alias Tuple!(float, "x", float, "y", float, "z") Coord;
    Coord c;
    c.field[1] = 1;   // access by index
    c.z = 1;          // access by given name
    alias Tuple!(string, string) DicEntry; // names can be omitted

    // enumerated values with conversions to and from strings
    mixin(defineEnum!("Openmode", "READ", "WRITE", "READWRITE", "APPEND"));
    void foo()
    {
        Openmode m = Openmode.READ;
        string s = enumToString(m);
        assert(s == "READ");
        Openmode m1;
        assert(enumFromString(s, m1) && m1 == m);
    }

    // Rebindable references to const and immutable objects
    void bar()
    {
        const w1 = new Widget, w2 = new Widget;
        w1.foo();
        // w1 = w2 would not work; can't rebind const object
        auto r = Rebindable!(const Widget)(w1);
        // invoke method as if r were a Widget object
        r.foo();
        // rebind r to refer to another object
        r = w2;
    }

License:
Boost License 1.0.

Authors:
Andrei Alexandrescu, Bartosz Milewski, Don Clugston, Shin Fujishiro

struct Unique(T);
  Encapsulates unique ownership of a resource. Resource of type T is deleted at the end of the scope, unless it is transferred. The transfer can be explicit, by calling release, or implicit, when returning Unique from a function. The resource can be a polymorphic class object, in which case Unique behaves polymorphically too.

  Example:

  this(RefT p);
    Constructor that takes an rvalue. It will ensure uniqueness, as long as the rvalue isn't just a view on an lvalue (e.g., a cast) Typical usage:

            Unique!(Foo) f = new Foo;

  this(ref RefT p);
    Constructor that takes an lvalue. It nulls its source. The nulling will ensure uniqueness as long as there are no previous aliases to the source.

  Unique release();
    Returns a unique rvalue. Nullifies the current contents

  RefT opDot();
    Forwards member access to contents

struct Tuple(T...);
  Tuple of values, for example Tuple!(int, string) is a record that stores an int and a string. Tuple can be used to bundle values together, notably when returning multiple values from a function. If obj is a tuple, the individual members are accessible with the syntax obj.field[0] for the first field, obj.field[1] for the second, and so on.

  The choice of zero-based indexing instead of one-base indexing was motivated by the ability to use value tuples with various compile-time loop constructs (e.g. type tuple iteration), all of which use zero-based indexing.

  Example:

      Tuple!(int, int) point;
      // assign coordinates
      point.field[0] = 5;
      point.field[1] = 6;
      // read coordinates
      auto x = point.field[0];
      auto y = point.field[1];

  Tuple members can be named. It is legal to mix named and unnamed members. The method above is still applicable to all fields.

  Example:

      alias Tuple!(int, "index", string, "value") Entry;
      Entry e;
      e.index = 4;
      e.value = "Hello";
      assert(e.field[1] == "Hello");
      assert(e.field[0] == 4);

  Tuples with named fields are distinct types from tuples with unnamed fields, i.e. each naming imparts a separate type for the tuple. Two tuple differing in naming only are still distinct, even though they might have the same structure.

  Example:

      Tuple!(int, "x", int, "y") point1;
      Tuple!(int, int) point2;
      assert(!is(typeof(point1) == typeof(point2))); // passes

  alias Types;
    The type of the tuple's components.

  template __ctor(U...) if (U.length == 0)
    Default constructor.

  template __ctor(U...) if (U.length == Types.length)
    Constructor taking one value for each field. Each argument must be implicitly assignable to the respective element of the target.

  template __ctor(V = void,U...)
    Constructor taking a compatible tuple. Each element of the source must be implicitly assignable to the respective element of the target.

  template opEquals(T) if (is(typeof(T.field)))
    Comparison for equality.

    bool opEquals(T rhs);
      Comparison for equality.

  template opCmp(T) if (is(typeof(T.field)))
    Comparison for ordering.

    int opCmp(T rhs);
      Comparison for ordering.

  template assign(U) if (is(typeof(U.init.field[0])))
    Assignment from another tuple. Each element of the source must be implicitly assignable to the respective element of the target.

    void assign(U rhs);
      Assignment from another tuple. Each element of the source must be implicitly assignable to the respective element of the target.

  template slice(uint from,uint to)
    Takes a slice of the tuple.

    Example:

        Tuple!(int, string, float, double) a;
        a.field[1] = "abc";
        a.field[2] = 4.5;
        auto s = a.slice!(1, 3);
        static assert(is(typeof(s) == Tuple!(string, float)));
        assert(s.field[0] == "abc" && s.field[1] == 4.5);

  string toString();
    Converts to string.

Tuple!(T) tuple(T...)(T args);
  Returns a Tuple object instantiated and initialized according to the arguments.

  Example:

      auto value = tuple(5, 6.7, "hello");
      assert(value.field[0] == 5);
      assert(value.field[1] == 6.7);
      assert(value.field[2] == "hello");

template defineEnum(string name,T...)
  Defines truly named enumerated values with parsing and stringizing primitives.

  Example:

      mixin(defineEnum!("Abc", "A", "B", 5, "C"));

  is equivalent to the following code:

      enum Abc { A, B = 5, C }
      string enumToString(Abc v) { ... }
      Abc enumFromString(string s) { ... }

  The enumToString function generates the unqualified names of the enumerated values, i.e. "A", "B", and "C". The enumFromString function expects one of "A", "B", and "C", and throws an exception in any other case.

  A base type can be specified for the enumeration like this:

      mixin(defineEnum!("Abc", ubyte, "A", "B", "C", 255));

  In this case the generated enum will have a ubyte representation.

template Rebindable(T) if (is(T == class) || is(T == interface) || isArray!(T))
  Rebindable!(T) is a simple, efficient wrapper that behaves just like an object of type T, except that you can reassign it to refer to another object. For completeness, Rebindable!(T) aliases itself away to T if T is a non-const object type. However, Rebindable!(T) does not compile if T is a non-class type.

  Regular const object references cannot be reassigned:

      class Widget { int x; int y() const { return a; } }
      const a = new Widget;
      a.y();          // fine
      a.x = 5;        // error! can't modify const a
      a = new Widget; // error! can't modify const a

  However, Rebindable!(Widget) does allow reassignment, while otherwise behaving exactly like a const Widget:

      auto a = Rebindable!(const Widget)(new Widget);
      a.y();          // fine
      a.x = 5;        // error! can't modify const a
      a = new Widget; // fine

  You may want to use Rebindable when you want to have mutable storage referring to const objects, for example an array of references that must be sorted in place. Rebindable does not break the soundness of D's type system and does not incur any of the risks usually associated with cast.

Rebindable!(T) rebindable(T)(T obj);
  Convenience function for creating a Rebindable using automatic type inference.

Rebindable!(T) rebindable(T)(Rebindable!(T) obj);
  This function simply returns the Rebindable object passed in. It's useful in generic programming cases when a given object may be either a regular class or a Rebindable.

char[] alignForSize(E...)(string[E.length] names);
  Order the provided members to minimize size while preserving alignment. Returns a declaration to be mixed in.

  Example:

      struct Banner {
        mixin(alignForSize!(byte[6], double)(["name", "height"]));
      }

  Alignment is not always optimal for 80-bit reals, nor for structs declared as align(1).

  BUG:
  bugzilla 2029 prevents the signature from being (string[] names...), so we need to use an ugly array literal instead.

template BlackHole(Base)
  BlackHole!Base is a subclass of Base which automatically implements all abstract member functions in Base as do-nothing functions. Each auto-implemented function just returns the default value of the return type without doing anything.

  The name came from Class::BlackHole Perl module by Sean M. Burke.

  Example:

      abstract class C
      {
          int m_value;
          this(int v) { m_value = v; }
          int value() @property { return m_value; }

          abstract real realValue() @property;
          abstract void doSomething();
      }

      void main()
      {
          auto c = new BlackHole!C(42);
          writeln(c.value);     // prints "42"

          // Abstract functions are implemented as do-nothing:
          writeln(c.realValue); // prints "NaN"
          c.doSomething();      // does nothing
      }

  See Also:
  AutoImplement, generateEmptyFunction

template WhiteHole(Base)
  WhiteHole!Base is a subclass of Base which automatically implements all abstract member functions as throw-always functions. Each auto-implemented function fails with throwing an Error and does never return. Useful for trapping use of not-yet-implemented functions.

  The name came from Class::WhiteHole Perl module by Michael G Schwern.

  Example:

      class C
      {
          abstract void notYetImplemented();
      }

      void main()
      {
          auto c = new WhiteHole!C;
          c.notYetImplemented(); // throws an Error
      }

  BUGS:
  Nothrow functions cause program to abort in release mode because the trap is implemented with assert(0) for nothrow functions.

  See Also:
  AutoImplement, generateAssertTrap

class AutoImplement(Base,alias how,alias what = isAbstractFunction): Base;
  AutoImplement automatically implements (by default) all abstract member functions in the class or interface Base in specified way.

  Parameters:

  how | template which specifies how functions will be implemented/overridden. Two arguments are passed to how: the type Base and an alias to an implemented function. Then how must return an implemented function body as a string. The generated function body can use these keywords: a0, a1, …: arguments passed to the function; args: a tuple of the arguments; self: an alias to the function itself; parent: an alias to the overridden function (if any). You may want to use templated property functions (instead of Implicit Template Properties) to generate complex functions:
      // Prints log messages for each call to overridden functions.
      string generateLogger(C, alias fun)() @property
      {
          enum qname = C.stringof ~ "." ~ __traits(identifier, fun);
          string stmt;

          stmt ~= q{ struct Importer { import std.stdio; } };
          stmt ~= `Importer.writeln("Log: ` ~ qname ~ `(", args, ")");`;
          static if (!__traits(isAbstractFunction, fun))
          {
              static if (is(typeof(return) == void))
                  stmt ~= q{ parent(args); };
              else
                  stmt ~= q{
                      auto r = parent(args);
                      Importer.writeln("--> ", r);
                      return r;
                  };
          }
          return stmt;
      }
  what | template which determines what functions should be implemented/overridden. An argument is passed to what: an alias to a non-final member function in Base. Then what must return a boolean value. Return true to indicate that the passed function should be implemented/overridden.
      // Sees if fun returns something.
      template hasValue(alias fun)
      {
          enum bool hasValue = !is(ReturnType!(fun) == void);
      }

  Note:
  Generated code is inserted in the scope of std.typecons module. Thus, any useful functions outside std.typecons cannot be used in the generated code. To workaround this problem, you may import necessary things in a local struct, as done in the generateLogger() template in the above example.

  BUGS:
  - Variadic arguments to constructors are not forwarded to super.
  - Deep interface inheritance causes compile error with messages like "Error: function std.typecons.AutoImplement!(Foo).AutoImplement.bar does not override any function". [Bugzilla 2525, Bugzilla 3525]
  - The parent keyword is actually a delegate to the super class' corresponding member function. [Bugzilla 2540]
  - Using alias template parameter in how and/or what may cause strange compile error. Use template tuple parameter instead to workaround this problem. [Bugzilla 4217]

template generateEmptyFunction(C,func...)
template generateAssertTrap(C,func...)
  Predefined how-policies for AutoImplement. These templates are used by BlackHole and WhiteHole, respectively.

enum RefCountedAutoInitialize;
  Options regarding auto-initialization of a RefCounted object (see the definition of RefCounted below).

  no
    Do not auto-initialize the object

  yes
    Auto-initialize the object

struct RefCounted(T,RefCountedAutoInitialize autoInit = RefCountedAutoInitialize.yes) if (!is(T == class));
  Defines a reference-counted object containing a T value as payload. RefCounted keeps track of all references of an object, and when the reference count goes down to zero, frees the underlying store. RefCounted uses malloc and free for operation.

  RefCounted is unsafe and should be used with care. No references to the payload should be escaped outside the RefCounted object.

  The autoInit option makes the object ensure the store is automatically initialized. Leaving autoInit == RefCountedAutoInitialize.yes (the default option) is convenient but has the cost of a test whenever the payload is accessed. If autoInit == RefCountedAutoInitialize.no, user code must call either refCountedIsInitialized or refCountedEnsureInitialized before attempting to access the payload. Not doing so results in null pointer dereference.

  Example:

      // A pair of an int and a size_t - the latter being the
      // reference count - will be dynamically allocated
      auto rc1 = RefCounted!int(5);
      assert(rc1 == 5);
      // No more allocation, add just one extra reference count
      auto rc2 = rc1;
      // Reference semantics
      rc2 = 42;
      assert(rc1 == 42);
      // the pair will be freed when rc1 and rc2 go out of scope

  template __ctor(A...) if (A.length > 0)
    Constructor that initializes the payload.

    Postcondition:
    refCountedIsInitialized

  void opAssign(typeof(this) rhs);
  void opAssign(T rhs);
    Assignment operators

  T refCountedPayload();
    Returns a reference to the payload. If (autoInit == RefCountedAutoInitialize.yes), calls refCountedEnsureInitialized. Otherwise, just issues assert(refCountedIsInitialized). Used with alias refCountedPayload this;, so callers can just use the RefCounted object as a T.

Copyright the respective authors, 2008- | Page generated by Ddoc.