Skip to content

Instantly share code, notes, and snippets.

@vporton
Last active May 9, 2019 14:45
Show Gist options
  • Save vporton/c06dd662a7e9a8c7655da07627a9f968 to your computer and use it in GitHub Desktop.
Save vporton/c06dd662a7e9a8c7655da07627a9f968 to your computer and use it in GitHub Desktop.

Modify tuple modifiers

The problem

In the standard D library it seems missing a function to modify tuple modifiers.

Consider the following:

alias t = AliasSeq!(int, float); // create tuple (int, float) of two types
alias tc = addTupleModifiers!("const shared", t);
static assert(is(tc[1] == const shared float)); // check that "const shared" was added to the second element of the tuple

Here addTupleModifiers is a template that adds modifiers (in this example “const shared”) to each element of a tuple. (So tc becomes a tuple (const shared int, const shared float).)

Note that in D adding an already present tuple modifier is a no-op. So if it were:

alias t = AliasSeq!(int, const float);

the result would be the same.

Also note that if we write instead:

alias tc = const shared(t);

this does not work in DMD v2.085.1, it does not work (without any error messages const shared is not added). Not sure if this is a compiler bug. I’ve reported it.

The implementation

Now I will show my implementation of addTupleModifiers:

template addTupleModifiers(string modifiers, T...) {
    private template addModifier(T1) {
        mixin("alias addModifier = " ~ modifiers ~ " T1;");
    }

    alias addTupleModifiers = staticMap!(addModifier, T);
}

This implementation uses a string mixin (a construct which creates code from a string calculated at compile time) to create the template addModifier (eponymous template, what in this case means that addModifier.addModifier can be shortened to just addModifier, because the member has the same name as this tempalte) and the template std.meta.staticMap from the standard library to apply the template addModifier to each element of the tuple.

Also note that it uses the construct T... (a variadic template) to provide an arbitrary number of types as arguments to our template.

The above code is present in my short library tuple-modifiers (which you can install with DUB, see also https://github.com/vporton/tuple-modifiers-dlang) under the Apache 2.0 license.

Possible usage

One possible usage of this template is to create a function g() having the same arguments as function f() but with const added to every argument (this is useful mostly in templates, especially ones with variadic arguments):

import std.traits;

string f(int x, float y) { return "xxx"; }

ReturnType!f g(addTupleModifiers!("const", Parameters!f) args) { return f(args); }

Here they are used the templates ReturnType and Parameters from std.meta which return correspondingly the return type and parameters types tuple for a function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment