On Wednesday, 21 June 2017 at 19:39:14 UTC, timvol wrote:
Hi! I've a simple array of bytes I received using sockets. What
I want to do is to calculate the target length of the message.
So, I defined a calcLength() function for each function code
(it's the first byte in my array). My problem is that I defined
the calcLength() function using conditions so that each
calcLength should be called depending on the respective
function code, see below:
module example;
private
{
size_t calcLength(ubyte ubFuncCode)() if ( ubFuncCode == 1 )
{
return 10; // More complex calculated value
}
size_t calcLength(ubyte ubFuncCode)() if ( ubFuncCode == 2 )
{
return 20; // More complex calculated value
}
size_t calcLength(ubyte ubFuncCode)() if ( ubFuncCode == 3 )
{
return 30; // More complex calculated value
}
}
size_t doCalcLength(ubyte ubFuncCode)
{
return calcLength!(ubFuncCode)();
}
int main()
{
doCalcLength(1);
return 0;
}
But... how can I execute these functions? I mean, calling
doCalcLength(1) function says "Variable ubFuncCode cannot be
read at compile time". So my idea is to create an array during
compile time using traits (e.g. __traits(allMembers)) and to
check this later during runtime. For illustration purposes
something like this:
--> During compile time:
void function()[ubyte] calcLengthArray;
auto tr = __traits(allMembers, example);
foreach ( string s; tr )
{
calcLengthArray[__trait(get<ubFuncCode>, s)] = s;
}
--> During runtime:
size_t doCalcLength(ubyte ubFuncCode)
{
auto length = 0;
if ( ubFuncCode in calcLengthArray )
{
length = calcLengthArray[ubFuncCode]!(ubFuncCode)();
}
return length;
}
I hope everyone knows what I want to do :). But... does anyone
know how I can realize that? I don't want to use a switch/case
structure because the calcLength() functions can be very
complex and I've over 40 different function codes. So, I think
the best approach is to use something similar to the one I
described.
Let us to look at your function:
size_t calcLength(ubyte ubFuncCode)() if ( ubFuncCode == 1 )
{
return 10; // More complex calculated value
}
This function accepts only one template parameter and no other
parameters. Template parameter should be known at compile time.
You can't pass a value read from socket, because you can read
from socket only at runtime. It is what the error message says.
You calls such function as follows:
calcLength!1()
calcLength!2()
and so on.
Your doCalcLength won't work for the same reason. You try to pass
"ubFuncCode" known at runtime as a template parameter, you will
get the same error.
You can try to instantiate all calcLength overloads and save them
in calcLengthArray at some index just like you already do, but
without any template parameters. The call would look something
like:
length = calcLengthArray[ubFuncCode]();
But it is simplier and shorter just to use a switch statement:
switch (ubFuncCode)
{
case 1:
Do what calcLength!1() would do
break;
case 2:
Do what calcLength!2() would do
break;
default:
break;
}