Difference between revisions of "Is expression"

From D Wiki
Jump to: navigation, search
(Initial commit: quick summary with a simple example)
 
(Added basic usage examples)
Line 4: Line 4:
 
* [http://dlang.org/expression.html dlang.org/expression]
 
* [http://dlang.org/expression.html dlang.org/expression]
  
=== Example ===
+
The following are simple demonstrations of the "is" expression, distilled from the main site:
 +
 
 +
<source lang="D">
 +
import std.stdio;
 +
void main()
 +
{
 +
    assert( !is(Foo) ); // Foo isnt a type, yet...
 +
    struct Foo {}
 +
    assert( is(Foo) );
 +
 
 +
    short x = 1;
 +
    assert( is(typeof(x) == short) );
 +
    assert( is(typeof(x) :  int  ) ); // can be implicitly converted
 +
 
 +
    alias double MyDubble;
 +
    void foo(MyDubble x) {
 +
        static if( is(MyDubble T) ) {
 +
            writeln("MyDubble is a double");
 +
        }
 +
    }
 +
    // foo("hello"); // T is a string: fail
 +
    foo(4.2);        // T is a double: pass
 +
 
 +
    alias real MyReal;
 +
    void bar(MyReal y) {
 +
        static if( is(MyReal T : float) ) {
 +
            writeln("MyReal");
 +
        }
 +
    }
 +
    bar(3); // can be implicitly converted
 +
}
 +
</source>
 +
 
 +
===A More "Complex"  Example ===
 
A question was asked on [http://forum.dlang.org/group/digitalmars.D.learn DForum learning channel] about how to create a template that would accept any numeric type including complex types:
 
A question was asked on [http://forum.dlang.org/group/digitalmars.D.learn DForum learning channel] about how to create a template that would accept any numeric type including complex types:
 
[http://forum.dlang.org/thread/jbyixfbuefvdlttnyclu@forum.dlang.org relavent thread]
 
[http://forum.dlang.org/thread/jbyixfbuefvdlttnyclu@forum.dlang.org relavent thread]
Line 60: Line 93:
  
 
== Summary ==  
 
== Summary ==  
"is" expressions might seem simple at first glance, but there is much more under the surface.  The various forms of an "is" expression mean slightly different things, and knowing when and where to use them is important when writing templates.
+
"is" expressions might seem simple at first glance, but there is much more under the surface.  The various forms of an "is" expression mean slightly different things, and knowing when and where to use them is important when writing templates. Also, familiarize yourself with [http://dlang.org/phobos/std_traits.html std.traits], the most common type checks have already been done for you!  If you want to see how they are done, browse the Phobos source (traits.d)

Revision as of 06:37, 11 December 2012


"is" expressions are used for checking for valid types and are heavily used in template constraints.

The following are simple demonstrations of the "is" expression, distilled from the main site:

import std.stdio;
void main()
{
    assert( !is(Foo) ); // Foo isnt a type, yet...
    struct Foo {}
    assert( is(Foo) );

    short x = 1;
    assert( is(typeof(x) == short) );
    assert( is(typeof(x) :  int  ) ); // can be implicitly converted

    alias double MyDubble;
    void foo(MyDubble x) {
        static if( is(MyDubble T) ) {
            writeln("MyDubble is a double");
        }
    }
    // foo("hello"); // T is a string: fail
    foo(4.2);        // T is a double: pass

    alias real MyReal;
    void bar(MyReal y) {
        static if( is(MyReal T : float) ) {
            writeln("MyReal");
        }
    }
    bar(3); // can be implicitly converted
}

A More "Complex" Example

A question was asked on DForum learning channel about how to create a template that would accept any numeric type including complex types: relavent thread

This author (User:Jniehus) made several attempts to solve the poster's problem which "eventually" resulted in a final solution that looked like the following:

import std.stdio, std.conv, std.traits, std.complex;
template isComplex(T) {
    static if ( is(T == Complex!double) ) {
        enum bool isComplex = true;
    }
    else static if ( is(T == Complex!float) ) {
        enum bool isComplex = true;
    }
    else static if ( is(T == Complex!real) ) {
        enum bool isComplex = true;
    }
    else {
        enum bool isComplex = false;
    }
}

template isComplexOrNumeric(T) {
    enum bool isComplexOrNumeric = (isComplex!T || isNumeric!T);
}

class Example(T) if (isComplexOrNumeric!T) {
    T k = to!T(1);
}

void main() {
    auto x = new Example!(Complex!double)();
    writeln(x.k);
    auto y = new Example!double();
    writeln(y.k);
}

This unsightly "static if" chain was used because a Complex type is actually a template itself which can accept one of three primitive types; double, float, or real. But as a more experienced D programmer (Artur Skawina) pointed out, the "is" expression is flexible enough to accomodate situations like this. So instead of writing a "static if" statement for each possible template type, we can use the following syntax to infer the secondary types:

template isComplex(T) 
{
   static if ( is(T _ == Complex!CT, CT) ) {
      enum isComplex = true;
   }
   else {
      enum isComplex = false;
   }
}

This is clearly a more scalable solution.

Summary

"is" expressions might seem simple at first glance, but there is much more under the surface. The various forms of an "is" expression mean slightly different things, and knowing when and where to use them is important when writing templates. Also, familiarize yourself with std.traits, the most common type checks have already been done for you! If you want to see how they are done, browse the Phobos source (traits.d)