What's wrong with this template function?
Ali Çehreli
acehreli at yahoo.com
Thu Jan 3 19:38:39 UTC 2019
On 01/03/2019 10:49 AM, Machine Code wrote:
> I wrote a small routine to return the first member
I see that that's possible because the values of such members are known
at compile time in your case. Otherwise, you would need a mechanism that
would return the value of the first member for any object at runtime.
> of type T of a same
> type, like struct below, but the assert is reached albeit the "yes"
> message is printed. What am I missing? should I use something else than
> return keyword to return from a template function or what?
>
> struct Color
> {
> enum red = Color("red", 30);
> enum blue = Color("blue", 40);
> enum green = Color("green");
>
> string name;
> int value;
> alias value this;
> }
>
> the routine:
>
> T first(T)()
> {
> import std.string : format;
> pragma(msg, format!"types = %s"([__traits(derivedMembers, T)]));
>
> static foreach(field; [__traits(derivedMembers, T)])
> {
> // exit on first match
> pragma(msg, format!"member %s"(field));
> static if(is(typeof(__traits(getMember, T, field)) == T))
> {
> pragma(msg, "yes");
> return __traits(getMember, T, field);
> }
> else
> {
> pragma(msg, "no");
> }
> }
> import std.string : format;
> static assert(0,
> format!"no first member of type %s found"(T.stringof));
That will always be checked at compile time and will always fail because
that line is not excluded from the compilation by another compile-time
check. It is a part of the function body and the compiler will have to
compile it and fail that check.
> }
You're basically performing a search at compile time and want to fail if
something is not found. I came up with the following method where a
nested function is used to return an index. The outer code calls the
function to set a compile-time expression (found) and is able to check
that something is found. (There are too many size_t.max's in the code;
cleanup needed. :) )
struct Color
{
enum red = Color("red", 30);
enum blue = Color("blue", 40);
enum green = Color("green");
string name;
int value;
alias value this;
}
T first(T)()
{
import std.string : format;
pragma(msg, format!"types = %s"([__traits(derivedMembers, T)]));
alias fields = __traits(derivedMembers, T);
auto first_() {
auto result = size_t.max;
static foreach(i, field; fields)
{
// exit on first match
pragma(msg, format!"member %s"(field));
static if(is(typeof(__traits(getMember, T, field)) == T))
{
pragma(msg,"yes");
if (result == size_t.max) {
result = i;
}
}
else
{
pragma(msg, "no");
}
}
return result;
}
enum found = first_();
import std.string : format;
static assert(found != size_t.max,
format!"no first member of type %s found"(T.stringof));
return __traits(getMember, T, fields[found]);
}
void main() {
pragma(msg, first!Color);
}
Ali
More information about the Digitalmars-d-learn
mailing list