Sane API design (AKA C's #ifdef hell)

libxmoc libxmoc at gmail.com
Sat Apr 18 10:13:02 UTC 2026


On Friday, 17 April 2026 at 13:51:58 UTC, Adam D. Ruppe wrote:
> On Friday, 17 April 2026 at 10:32:37 UTC, Dennis wrote:
>> The effort needed to accommodate "complex library" and "all 
>> versions" by far eclipses the effort to write a little 
>> boilerplate like:
>
> Substitution static if for version opens the door for more 
> order of eval bugs in the compiler. I've never been able to 
> actually do it in a real world project.
>
> tbh though instead of versioning symbols i'd rather they be 
> like marked... better to say "function foo was introduced in 
> version 4.4 but you are using 4.3 compatibility flags" rather 
> than "undefined symbol: foo"

+1



On Friday, 17 April 2026 at 10:32:37 UTC, Dennis wrote:
> On Friday, 17 April 2026 at 08:08:57 UTC, Dejan Lekic wrote:
>> It becomes _much more_ complicated when you need to check for 
>> version, and depending on version declare functions. D does 
>> not offer good solution for this and that is where C 
>> preprocessor wins as we have to combine `version`s, enums, 
>> static ifs in order to achieve things that are quite simple 
>> with C preprocessor.
>>
>> Those who believe D is good for this should write a binding 
>> for a complex library that supports all versions.
>
> I'm looking at https://github.com/nigels-com/glew/tree/master 
> and https://github.com/BindBC/bindbc-opengl, and I wouldn't say 
> either is a winner.
>
> The effort needed to accommodate "complex library" and "all 
> versions" by far eclipses the effort to write a little 
> boilerplate like:
>
> ```D
> enum glSupport = (){
> 	version(GL_46)       return GLSupport.gl46;
> 	else version(GL_45)  return GLSupport.gl45;
> 	else version(GL_44)  return GLSupport.gl44;
> 	else version(GL_43)  return GLSupport.gl43;
> 	else version(GL_42)  return GLSupport.gl42;
> 	else version(GL_41)  return GLSupport.gl41;
> 	else version(GL_40)  return GLSupport.gl40;
> 	else version(GL_33)  return GLSupport.gl33;
> 	else version(GL_32)  return GLSupport.gl32;
> 	else version(GL_31)  return GLSupport.gl31;
> 	else version(GL_30)  return GLSupport.gl30;
> 	else                 return GLSupport.gl21;
> }();
> ```

I'm not a fan of this mindset, both are valuable, besides, this 
is exactly the problem. When the idiomatic answer to a problem is 
hack.., we need to kill this workaround culture and give people 
something that actually works.


dmd -define:GL=43

```
module gl;

import core.config; // dmd would build this on demand at import 
time


void draw() {
     static if (define.GL >= 33) {
         // use vao
     } else {
         // fallback old opengl
     }
}
```

This is just a random example, don't view this as a feature 
request.




More information about the Digitalmars-d mailing list