www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Check if function argument can be handled in CT

reply Andrey <saasecondbox yandex.ru> writes:
Hi all,
Do you know can we detect that some argument of a function can be 
handled in CT?
For example:
 int value1 = 10;
 someFunction(value1);
 int value2 = getValueFromUserInput();
 someFunction(value2);
 void someFunction(int arg)
{
    static if(argCanBeHandledInCT(arg))
    {
        // perform some calculations during compilation
    }
    else
    {
        // perform some calculations during runtime
    }
}
Such thing would be good for code optimisation. For example we pass some strings as arguments and in function they are concatenated. So instead of concating them in RT (and allocating memory) we can do all these actions in CT and get one resulting string.
Apr 24 2019
parent reply Basile.B <b2.temp gmx.com> writes:
On Wednesday, 24 April 2019 at 07:53:47 UTC, Andrey wrote:
 Hi all,
 Do you know can we detect that some argument of a function can 
 be handled in CT?
 For example:
 int value1 = 10;
 someFunction(value1);
 int value2 = getValueFromUserInput();
 someFunction(value2);
 void someFunction(int arg)
{
    static if(argCanBeHandledInCT(arg))
    {
        // perform some calculations during compilation
    }
    else
    {
        // perform some calculations during runtime
    }
}
Such thing would be good for code optimisation. For example we pass some strings as arguments and in function they are concatenated. So instead of concating them in RT (and allocating memory) we can do all these actions in CT and get one resulting string.
In your case I thing that you rather want to know if the function is called at compile-time I suppose, since the arg is clearly not a template value parameter so you must make a branch with the __ctfe variable if (__ctfe) {/*executed during compilation*/}else {executed when program runs} But otherwise you can know if something is know at compile time with this template: /** * Indicates wether something is a value known at compile time. * * Params: * V = The value to test. * T = Optional, the expected value type. */ template isCompileTimeValue(alias V, T...) if (T.length == 0 || (T.length == 1 && is(T[0]))) { enum isKnown = is(typeof((){enum v = V;})); static if (!T.length) enum isCompileTimeValue = isKnown; else enum isCompileTimeValue = isKnown && is(typeof(V) == T[0]); } /// unittest { string a; enum b = "0"; enum c = 0; static assert(!isCompileTimeValue!a); static assert(isCompileTimeValue!b); static assert(isCompileTimeValue!c); static assert(isCompileTimeValue!(b,string)); static assert(isCompileTimeValue!(c,int)); static assert(!isCompileTimeValue!(c,char)); static assert(!isCompileTimeValue!(char)); } taken from iz (https://github.com/Basile-z/iz/blob/master/import/iz/types.d#L602)
Apr 24 2019
parent reply Andrey <saasecondbox yandex.ru> writes:
On Wednesday, 24 April 2019 at 08:28:06 UTC, Basile.B wrote:
 On Wednesday, 24 April 2019 at 07:53:47 UTC, Andrey wrote:
I know about this template. Unfortunally, it doesn't work inside functions.
 void test(string arg1, string arg2)
 {
     enum isKnown1 = is(typeof((){enum v = arg1;}));
     enum isKnown2 = is(typeof((){enum v = arg2;}));
     writeln(isKnown1);
     writeln(isKnown2);
 }
 
 void main()
 {
     test("qwerty", "qaz");
 }
Output:
 false
 false
And I don't want to execute function using CTFE. The function should be ran as usual. Example:
 char[] test(string arg1, string arg2)
 {
     static if(isCTArg(arg1) && isCTArg(arg2))
     {
         enum result = "CT: " ~ arg1 ~ " and " ~ arg2; // no 
 allocations
         return result;
     }
     else
     {
         import std.format : format;
 
         auto result = format!"RT: %s and %s"(arg1, arg2); // at 
 least 1 allocation
         return result;
     }
 }
 
 void main()
 {
     // ...
     auto val = test(some_CT_or_RT_arg1, some_CT_or_RT_arg2); // 
 not CTFE.
     // ...
 }
Apr 24 2019
parent Mike Parker <aldacron gmail.com> writes:
On Wednesday, 24 April 2019 at 10:52:58 UTC, Andrey wrote:
 On Wednesday, 24 April 2019 at 08:28:06 UTC, Basile.B wrote:
 On Wednesday, 24 April 2019 at 07:53:47 UTC, Andrey wrote:
I know about this template. Unfortunally, it doesn't work inside functions.
 void test(string arg1, string arg2)
 {
     enum isKnown1 = is(typeof((){enum v = arg1;}));
     enum isKnown2 = is(typeof((){enum v = arg2;}));
     writeln(isKnown1);
     writeln(isKnown2);
 }
 
 void main()
 {
     test("qwerty", "qaz");
 }
Output:
 false
 false
And I don't want to execute function using CTFE. The function should be ran as usual. Example:
 char[] test(string arg1, string arg2)
 {
     static if(isCTArg(arg1) && isCTArg(arg2))
     {
         enum result = "CT: " ~ arg1 ~ " and " ~ arg2; // no 
 allocations
         return result;
     }
     else
     {
         import std.format : format;
 
         auto result = format!"RT: %s and %s"(arg1, arg2); // 
 at least 1 allocation
         return result;
     }
 }
 
 void main()
 {
     // ...
     auto val = test(some_CT_or_RT_arg1, some_CT_or_RT_arg2); 
 // not CTFE.
     // ...
 }
arg1 and arg2 are *never* compile-time arguments. If a function is executed at compile time, the function may be passed arguments that are compile-time values, but inside the function, the arguments are interpreted as if it were running at runtime. That means that you can't assign function arguments to enums.
Apr 24 2019