Difference between revisions of "Is expression"

From D Wiki
Jump to: navigation, search
m
m (Adding ref link to Ali's book)
Line 2: Line 2:
 
"is" expressions are used for checking for valid types and are heavily used in template constraints.   
 
"is" expressions are used for checking for valid types and are heavily used in template constraints.   
 
* [http://dlang.org/expression.html dlang.org/expression]
 
* [http://dlang.org/expression.html dlang.org/expression]
 +
* [http://ddili.org/ders/d.en/is_expr.html Programming in D - is Expression]
  
 
The following are simple demonstrations of the "is" expression, distilled from the main site:
 
The following are simple demonstrations of the "is" expression, distilled from the main site:
Line 37: Line 38:
  
 
===A More "Complex"  Example ===
 
===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://form.dlang.org DForum learning channel] about how to create a template that would accept any numeric type including complex types. 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:
[http://forum.dlang.org/thread/jbyixfbuefvdlttnyclu@forum.dlang.org 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:
 
  
 
<source lang="D">
 
<source lang="D">

Revision as of 02:44, 11 October 2015

"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) ); // now it is

    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. 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 for traits.d.