www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Conditional compilation on availability?

reply Fredrik Olsson <peylow gmail.com> writes:
Might be an easy one, or a missing feature :).

But how do I do a conditional compilation on the availability of a 
function, variable, type or whatever?

For example:

class foo(T) {
  T[] bar;
   static if ("predicate for toString(T) exists") {
     char[] allBarsConcatinatedAsString() {
       char[] r = ""
       foreach (v; bar) {
	r ~= toString(v);
       }
     }
   }
}

What would I type instead of "predicate for toString(T) exists"?

// Fredrik
Jul 08 2006
next sibling parent reply Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Fredrik Olsson wrote:
 Might be an easy one, or a missing feature :).
 
 But how do I do a conditional compilation on the availability of a 
 function, variable, type or whatever?
 
 For example:
 
 class foo(T) {
  T[] bar;
   static if ("predicate for toString(T) exists") {
     char[] allBarsConcatinatedAsString() {
       char[] r = ""
       foreach (v; bar) {
     r ~= toString(v);
       }
     }
   }
 }
 
 What would I type instead of "predicate for toString(T) exists"?
 
 // Fredrik

class foo(T) { static if (is(typeof(toString(T.init)))) { // ... } } The IsExpression tests whether a given type is valid. typeof gets the type of a given expression. Thus, you can use one inside the other to test whether a given expression exists. Additionally, the expression inside of typeof is not actually executed, so it's safe to "call" the function like this. -- Kirk McDonald Pyd: Wrapping Python with D http://dsource.org/projects/pyd/wiki
Jul 08 2006
parent reply Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
Kirk McDonald wrote:
 Fredrik Olsson wrote:
 Might be an easy one, or a missing feature :).

 But how do I do a conditional compilation on the availability of a 
 function, variable, type or whatever?

 For example:

 class foo(T) {
  T[] bar;
   static if ("predicate for toString(T) exists") {
     char[] allBarsConcatinatedAsString() {
       char[] r = ""
       foreach (v; bar) {
     r ~= toString(v);
       }
     }
   }
 }

 What would I type instead of "predicate for toString(T) exists"?

 // Fredrik

class foo(T) { static if (is(typeof(toString(T.init)))) { // ... } } The IsExpression tests whether a given type is valid. typeof gets the type of a given expression. Thus, you can use one inside the other to test whether a given expression exists. Additionally, the expression inside of typeof is not actually executed, so it's safe to "call" the function like this.

Note that that doesn't work if T is a static array, since typeof(T) != typeof(T.init) but instead typeof(T.init) == typeof(*T) (which is viewed by some of us as a nasty inconsistency). Best to do as in Tom's example. -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 09 2006
parent reply Fredrik Olsson <peylow gmail.com> writes:
Bruno Medeiros skrev:
 Kirk McDonald wrote:
 
 Fredrik Olsson wrote:

 Might be an easy one, or a missing feature :).

 But how do I do a conditional compilation on the availability of a 
 function, variable, type or whatever?

 For example:

 class foo(T) {
  T[] bar;
   static if ("predicate for toString(T) exists") {
     char[] allBarsConcatinatedAsString() {
       char[] r = ""
       foreach (v; bar) {
     r ~= toString(v);
       }
     }
   }
 }

 What would I type instead of "predicate for toString(T) exists"?

 // Fredrik

class foo(T) { static if (is(typeof(toString(T.init)))) { // ... } } The IsExpression tests whether a given type is valid. typeof gets the type of a given expression. Thus, you can use one inside the other to test whether a given expression exists. Additionally, the expression inside of typeof is not actually executed, so it's safe to "call" the function like this.

Note that that doesn't work if T is a static array, since typeof(T) != typeof(T.init) but instead typeof(T.init) == typeof(*T) (which is viewed by some of us as a nasty inconsistency). Best to do as in Tom's example.

Thanks Kirk, Tom and Bruno. I got it too work. But for a more general case perhaps: static if(expression) should yield false if expression is false, _or_ if the expression can not be resolved. So that for example these could work: static if (toString(int)) { /* jupp std.strings probably imported */ } static if (T.nan) { /* Would seem we have a float */ } etc. But that is just wishes. // Fredrik
Jul 09 2006
parent Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Fredrik Olsson wrote:
 But for a more general case perhaps:
 static if(expression) should yield false if expression is false, _or_ if 
 the expression can not be resolved. So that for example these could work:
 static if (toString(int)) { /* jupp std.strings probably imported */ }
 static if (T.nan) { /* Would seem we have a float */ }
 etc.
 
 But that is just wishes.

I'd be against it. At first it looks like a cool idea, until you think about modifying existing code. Say, you statically check some condition in your code, e.g. 'static if (foo.bar > 10)'. Then after a few committee meetings, it's decided that 'bar' should be renamed to 'baz'. So you get to work to change all 'bar' occurrences to 'baz'. But if you miss one... then 'static if (foo.bar > 10)' would always be false. An error should be triggered in that case IMO. You can still do these tests by using the 'static if (is(typeof()))' combo. -- Tomasz Stachowiak /+ a.k.a. h3r3tic +/
Jul 09 2006
prev sibling parent Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Fredrik Olsson wrote:
 Might be an easy one, or a missing feature :).
 
 But how do I do a conditional compilation on the availability of a 
 function, variable, type or whatever?
 
 For example:
 
 class foo(T) {
  T[] bar;
   static if ("predicate for toString(T) exists") {
     char[] allBarsConcatinatedAsString() {
       char[] r = ""
       foreach (v; bar) {
     r ~= toString(v);
       }
     }
   }
 }
 
 What would I type instead of "predicate for toString(T) exists"?
 
 // Fredrik

The following seems to do the trick: import std.string; class foo(T) { T[] bar; static if (is(typeof(.toString(bar[0])))) { char[] allBarsConcatinatedAsString() { char[] r = ""; foreach (v; bar) { r ~= .toString(v); } return r; } } } void main() { auto a = new foo!(int); a.allBarsConcatinatedAsString(); struct Blah {} auto b = new foo!(Blah); //b.allBarsConcatinatedAsString(); } -- Tomasz Stachowiak /+ a.k.a. h3r3tic +/
Jul 08 2006