Difference between revisions of "Is expression"

From D Wiki
Jump to: navigation, search
m (Adding ref link to Ali's book)
m (correct forum link)
 
(3 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
{{DISPLAYTITLE:is expression}}
 
{{DISPLAYTITLE:is expression}}
 
"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://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 38: Line 36:
  
 
===A More "Complex"  Example ===
 
===A More "Complex"  Example ===
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:
+
A question was asked on [https://forum.dlang.org the D forum] 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:
  
 
<source lang="D">
 
<source lang="D">
Line 78: Line 76:
 
template isComplex(T)  
 
template isComplex(T)  
 
{
 
{
   static if ( is(T _ == Complex!CT, CT) ) {
+
   static if ( is(T == Complex!CT, CT) ) {
 
       enum isComplex = true;
 
       enum isComplex = true;
 
   }
 
   }
Line 91: Line 89:
 
== 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.  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 for traits.d.
 
"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 for traits.d.
 +
 +
== External links ==
 +
* [http://dlang.org/spec/expression.html#IsExpression IsExpression] spec
 +
* [http://ddili.org/ders/d.en/is_expr.html Programming in D - is Expression]
  
 
[[Category:Expressions]]
 
[[Category:Expressions]]

Latest revision as of 05:06, 14 April 2024

"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 the D forum 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.

External links