digitalmars.D.learn - checking if template arg is literal, possible ER for compiler change
- ketmar via Digitalmars-d-learn (76/76) Jan 08 2015 Hello.
Hello. disclaimer: please, ignore compiler inlining abilities while you are reading this post. i'll give some reasoning later. let's imagine that we have such function: void putPixel (int x, int y, uint color) { if ((color&0xff) =3D=3D 0) { // replace pixel } else if ((color&0xff) !=3D 0xff) { // do color blending } // and do nothing for transparent pixels } and it's often calling like this: `putPixel(x, y, Color.White);` (or another color constant). `Color.White` is not transparent. but why we should do all the checks if we know the argument value at compile time? it would be wonderful if we'll be able to do something like this: void putPixel() (int x, int y, uint color) { static if (isLiteralArg!color) { static if ((literalArgValue!color&0xff) =3D=3D 0) { // replace pixel } else static if ((literalArgValue!color&0xff) !=3D 0xff) { // do color blending with code // optimised for the given color } // and do nothing for transparent pixels } else { if ((color&0xff) =3D=3D 0) { // replace pixel } else if ((color&0xff) !=3D 0xff) { // do color blending } // and do nothing for transparent pixels } } i named new traits `isLiteralArg` and `literalArgValue` here. yes, we see code duplication here, but this is another story. what is important is that we can generate specialised versions of `putPixel` based on argument value which is known in compile time. sure, for easy cases like this we can rely on compiler inlining abilities. yet inlining may fail without warning (having warning about failing inlines is nice, but this is completely different story). and what is much more important is that we can specialise `putPixel` with known color value. we can, for example, generate different code for different opacities and so on. we can introduce range checking for `x` and `y` and omit that if we know their values at compile time. the thing is that we have "controlled inlining" here without resorting to something like this: void putPixel(alias x, alias y, alias color) () if (isIntegral!(typeof(x)) && isIntegral!(typeof(y)) && isIntegral!(typeof(color)) { static if (!is(color)) { // color is literal } else { // color is not known in compile time } } besides looking ugly with all those `isIntegral!` checks, which makes signature unreadable, we now forced to call it like `putPixel!(x, y, c);` instead of `putPixel(x, y, c);`. ah, and compiler error messages are not really readable in this case. what i want to say here is that having a way to check if *function* args for templated function are literals (and get their values) can be useful for various patterns of compile-time code generation and parameterization without resorting to ugly signatures and unnatural "bang calling". this can break template instantiation though, as we cannot assume that template with identical argument types will instantiate to identical functions, but i don't think that this is of great importance: compiler can do AST comparisons on various instances later. this will change some instantiated function signatures too, as they now will depend of literal arguments. so it will be wise to do this only for templates that explicitly used `isLiteralArg` and `literalArgValue` traits. this seems to be a not-so-small change of compiler internals, so i want to know if i'm completely insane here or there are more people that see a sane practical value in such feature.
Jan 08 2015