mirror of git://gcc.gnu.org/git/gcc.git
213 lines
6.2 KiB
D
213 lines
6.2 KiB
D
/**
|
|
* Contains traits for runtime internal usage.
|
|
*
|
|
* Copyright: Copyright Digital Mars 2014 -.
|
|
* License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
|
|
* Authors: Martin Nowak
|
|
* Source: $(DRUNTIMESRC core/internal/_traits.d)
|
|
*/
|
|
module core.internal.traits;
|
|
|
|
/// taken from std.typetuple.TypeTuple
|
|
template TypeTuple(TList...)
|
|
{
|
|
alias TypeTuple = TList;
|
|
}
|
|
|
|
T trustedCast(T, U)(auto ref U u) @trusted pure nothrow
|
|
{
|
|
return cast(T)u;
|
|
}
|
|
|
|
template Unconst(T)
|
|
{
|
|
static if (is(T U == immutable U)) alias Unconst = U;
|
|
else static if (is(T U == inout const U)) alias Unconst = U;
|
|
else static if (is(T U == inout U)) alias Unconst = U;
|
|
else static if (is(T U == const U)) alias Unconst = U;
|
|
else alias Unconst = T;
|
|
}
|
|
|
|
/// taken from std.traits.Unqual
|
|
template Unqual(T)
|
|
{
|
|
version (none) // Error: recursive alias declaration @@@BUG1308@@@
|
|
{
|
|
static if (is(T U == const U)) alias Unqual = Unqual!U;
|
|
else static if (is(T U == immutable U)) alias Unqual = Unqual!U;
|
|
else static if (is(T U == inout U)) alias Unqual = Unqual!U;
|
|
else static if (is(T U == shared U)) alias Unqual = Unqual!U;
|
|
else alias Unqual = T;
|
|
}
|
|
else // workaround
|
|
{
|
|
static if (is(T U == immutable U)) alias Unqual = U;
|
|
else static if (is(T U == shared inout const U)) alias Unqual = U;
|
|
else static if (is(T U == shared inout U)) alias Unqual = U;
|
|
else static if (is(T U == shared const U)) alias Unqual = U;
|
|
else static if (is(T U == shared U)) alias Unqual = U;
|
|
else static if (is(T U == inout const U)) alias Unqual = U;
|
|
else static if (is(T U == inout U)) alias Unqual = U;
|
|
else static if (is(T U == const U)) alias Unqual = U;
|
|
else alias Unqual = T;
|
|
}
|
|
}
|
|
|
|
// Substitute all `inout` qualifiers that appears in T to `const`
|
|
template substInout(T)
|
|
{
|
|
static if (is(T == immutable))
|
|
{
|
|
alias substInout = T;
|
|
}
|
|
else static if (is(T : shared const U, U) || is(T : const U, U))
|
|
{
|
|
// U is top-unqualified
|
|
mixin("alias substInout = "
|
|
~ (is(T == shared) ? "shared " : "")
|
|
~ (is(T == const) || is(T == inout) ? "const " : "") // substitute inout to const
|
|
~ "substInoutForm!U;");
|
|
}
|
|
else
|
|
static assert(0);
|
|
}
|
|
|
|
private template substInoutForm(T)
|
|
{
|
|
static if (is(T == struct) || is(T == class) || is(T == union) || is(T == interface))
|
|
{
|
|
alias substInoutForm = T; // prevent matching to the form of alias-this-ed type
|
|
}
|
|
else static if (is(T : V[K], K, V)) alias substInoutForm = substInout!V[substInout!K];
|
|
else static if (is(T : U[n], U, size_t n)) alias substInoutForm = substInout!U[n];
|
|
else static if (is(T : U[], U)) alias substInoutForm = substInout!U[];
|
|
else static if (is(T : U*, U)) alias substInoutForm = substInout!U*;
|
|
else alias substInoutForm = T;
|
|
}
|
|
|
|
/// used to declare an extern(D) function that is defined in a different module
|
|
template externDFunc(string fqn, T:FT*, FT) if (is(FT == function))
|
|
{
|
|
static if (is(FT RT == return) && is(FT Args == function))
|
|
{
|
|
import core.demangle : mangleFunc;
|
|
enum decl = {
|
|
string s = "extern(D) RT externDFunc(Args)";
|
|
foreach (attr; __traits(getFunctionAttributes, FT))
|
|
s ~= " " ~ attr;
|
|
return s ~ ";";
|
|
}();
|
|
pragma(mangle, mangleFunc!T(fqn)) mixin(decl);
|
|
}
|
|
else
|
|
static assert(0);
|
|
}
|
|
|
|
template staticIota(int beg, int end)
|
|
{
|
|
static if (beg + 1 >= end)
|
|
{
|
|
static if (beg >= end)
|
|
{
|
|
alias staticIota = TypeTuple!();
|
|
}
|
|
else
|
|
{
|
|
alias staticIota = TypeTuple!(+beg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
enum mid = beg + (end - beg) / 2;
|
|
alias staticIota = TypeTuple!(staticIota!(beg, mid), staticIota!(mid, end));
|
|
}
|
|
}
|
|
|
|
template dtorIsNothrow(T)
|
|
{
|
|
enum dtorIsNothrow = is(typeof(function{T t=void;}) : void function() nothrow);
|
|
}
|
|
|
|
template anySatisfy(alias F, T...)
|
|
{
|
|
static if (T.length == 0)
|
|
{
|
|
enum anySatisfy = false;
|
|
}
|
|
else static if (T.length == 1)
|
|
{
|
|
enum anySatisfy = F!(T[0]);
|
|
}
|
|
else
|
|
{
|
|
enum anySatisfy =
|
|
anySatisfy!(F, T[ 0 .. $/2]) ||
|
|
anySatisfy!(F, T[$/2 .. $ ]);
|
|
}
|
|
}
|
|
|
|
// Somehow fails for non-static nested structs without support for aliases
|
|
template hasElaborateDestructor(T...)
|
|
{
|
|
static if (is(T[0]))
|
|
alias S = T[0];
|
|
else
|
|
alias S = typeof(T[0]);
|
|
|
|
static if (is(S : E[n], E, size_t n) && S.length)
|
|
{
|
|
enum bool hasElaborateDestructor = hasElaborateDestructor!E;
|
|
}
|
|
else static if (is(S == struct))
|
|
{
|
|
enum hasElaborateDestructor = __traits(hasMember, S, "__dtor")
|
|
|| anySatisfy!(.hasElaborateDestructor, S.tupleof);
|
|
}
|
|
else
|
|
enum bool hasElaborateDestructor = false;
|
|
}
|
|
|
|
// Somehow fails for non-static nested structs without support for aliases
|
|
template hasElaborateCopyConstructor(T...)
|
|
{
|
|
static if (is(T[0]))
|
|
alias S = T[0];
|
|
else
|
|
alias S = typeof(T[0]);
|
|
|
|
static if (is(S : E[n], E, size_t n) && S.length)
|
|
{
|
|
enum bool hasElaborateCopyConstructor = hasElaborateCopyConstructor!E;
|
|
}
|
|
else static if (is(S == struct))
|
|
{
|
|
enum hasElaborateCopyConstructor = __traits(hasMember, S, "__postblit")
|
|
|| anySatisfy!(.hasElaborateCopyConstructor, S.tupleof);
|
|
}
|
|
else
|
|
enum bool hasElaborateCopyConstructor = false;
|
|
}
|
|
|
|
// std.meta.Filter
|
|
template Filter(alias pred, TList...)
|
|
{
|
|
static if (TList.length == 0)
|
|
{
|
|
alias Filter = TypeTuple!();
|
|
}
|
|
else static if (TList.length == 1)
|
|
{
|
|
static if (pred!(TList[0]))
|
|
alias Filter = TypeTuple!(TList[0]);
|
|
else
|
|
alias Filter = TypeTuple!();
|
|
}
|
|
else
|
|
{
|
|
alias Filter =
|
|
TypeTuple!(
|
|
Filter!(pred, TList[ 0 .. $/2]),
|
|
Filter!(pred, TList[$/2 .. $ ]));
|
|
}
|
|
}
|