How can I construct an array of static regexes in D? - d

I have several regular expressions that need to be applied in a row. For example:
import std.regex;
auto ctrex1 = ctRegex!(`def\s\n`);
auto ctrex2 = ctRegex!(`func\(`);
I'd like to wrap them in an array and use it as a function argument.
StaticRegex!char[] staticRegexes = [ctrex1, ctrex2];
It does not work however and the compiler throws
Error: static variable ctrex1 cannot be read at compile time
My naive understanding is that after compiler reads and compiles ctrex1 and ctrex2 there should not be a problem for it to compile an array for these objects later below. Assuming it just reads the statements from top to bottom. But it looks like my understanding is wrong. How does compiler work in this case and how do I construct an array of static regexes?

You can't have an array of compile-time regular expression objects, because an array's values all must have the same type, but a compile-time regular expression has the expression string as a part of its type.
You could instead have a tuple of compile time regular expression objects, or add a level of indirection and wrap each into an uniform delegate, which then invokes the compile time regular expression object's matcher.

Related

How to determine if a parameter is a constexpr in compile-time

I have a compile-time string class that helps programs compute various relevant things at compile time, such as hash results and a quick lookup table for find, which is constructed like this:
"hello"_constexpr_str;
Also, my string class supports construction from this type, which allows for fast hash and fast find and avoids unnecessary data copying, like this.
defs::string string = "hello"_constexpr_str;
Of course, my string class also supports building from const char_T*
Now here's the problem!
I want to use the constexpr method automatically when my string class is constructed with compile-time constants like string("hell word!") rather than ugly but strong string("hell word!"_constexpr_str)
In other words, I want string("hell word!") to automatically become string("hell word!"_constexpr_str) in compile-time to calculate the information about the constant string and put it in constant state storage, so that all my string class has to do is hold a pointer to constexpr_str_t
//Draft Code
#if defined(__cpp_if_consteval)
#define if_in_consteval if consteval
#else
#define if_in_consteval if constexpr(0)
#endif
constexpr string_t(const constexpr_str_t&str)noexcept;//save a pointer to constexpr_str_t
string_t(const char_T* str)noexcept{
if_in_consteval{
constexpr constexpr_str_t constexpr_str(str);
construct[this](constexpr_str);
}
else{
construct[this](string_view_t(str));
}
}
What do I do to achieve this?
If I understood your question now after the discussion in the comments correctly, you have a operator""_constexpr_str which is marked consteval and returns a string-view-like type constexpr_str_t with some additional information attached based on the contents of the string.
You then have a function taking an (ordinary) string literal as argument with overloads taking either constexpr_str_t or const char*. You basically want the const char* overload to only be chosen when the argument is not a constant expression. Otherwise the constexpr_str_t overload should be chosen and constructed at compile-time (i.e. via consteval) so that the extra information can be attached at compile-time.
This cannot work however, because it is impossible to overload on consteval. Whether or not a consteval function is called depends only on the type of the argument. It is not possible to distinguish between constant expression arguments and non-constant expression arguments.
Trying to determine whether a function argument is a constant expression inside a function is also impossible. Functions are compiled individually. They are not compiled twice depending on whether or not the argument is a constant expression.
The only thing possible is to change behavior based on whether the whole expression that the function call is used in is a context requiring a constant expression. That is what if consteval is for. But if you are making a decision based on such a scenario, you don't need
constexpr constexpr_str_t constexpr_str(str);
You can simply do the calculation for the additional properties of the string there as if at runtime and mark the function constexpr. If used in a context requiring a constant expression it will be evaluated at compile-time.
If you want to enforce this even if the call doesn't happen in a context requiring a constant expression, then it is impossible.
You can however write a macro which tests whether an expression is a constant expression and then conditionally calls either a consteval function or a non-consteval function. It is just impossible through a function call.
You can use the C++20 std::is_constant_evaluated() function found in the <type_traits> header. It detects whether a function call occurs within a constant-evaluated context.

C++ Construct to check whether a local expression is not a constant expression

I'm looking for some construct that can detect whether a local expression is a constant expression, or whether it's not, that can be used in a static_assert declaration.
In code:
int main()
{
constexpr int i = 1;
if constexpr(i) {}
static_assert(is_constexpr(i));
int j = 1;
//if constexpr(j) {} // error: 'j' is not usable in a constant expression
static_assert(!is_constexpr(j));
}
The is_constexpr here can be a macro, a class (then probably with other syntax), or a function. How to make is_constexpr(i) return true/true_type and, conversely, is_constexpr(j) return false/false_type?
I tried a lot of the solutions available here on SO (also using old-school SFINAE) without success. I can edit in the links and my failed attempts if required.
Playground on godbolt here
The problem is that parameters (like t) are not constant expressions. For example, we cannot use t as a template non-type parameter, or as a size of a built-in array.
This means that some expression say some_expr( t ) that contains(involves) the subexpression t is itself not a constant expression, either.
Can is_constexpr be a function?
The simple fact that you write is_constexpr(i) means that you're looking for a function of type bool(auto); but you also want to be able to pass it constexpr arguments or non-constexpr arguments, so for sure it can't be consteval otherwise it would error when called in the latter scenario; so you can at most make it constexpr. However, there's no such a thing (yet?) as a constexpr function parameter, so as soon as you pass something to that constexpr function you have no way to detect whether or not the argument was a constant expression at the call site.
Can is_constexpr be a meta-function?
The other opportunity would be to use a metafunction, but how would you expect to call it? If you expect is_constexpr<i>, i.e. passing the entity you are querying as a template argument, that would be clearly only possible if i is constexpr; if you go for is_constexpr<decltype(x)>, you are expecting that decltype(x) contains some info about the constexpr-ness of x, but that's not the case, as constexpr/consteval are not part of the type of an expression.
Do you really need it?
This, I believe, means that whenever you ask whether an expression is a constant expression, you can always find the answer by looking at the code before that expression, and that answer will not depend on any boolean condition, not even a constexpr condition.
In other words, I believe (and happy to be proved wrong), there's no way for an expression appearing in a C++ program to be constexpr or not in the same line of code depending on the path that leads there.
Do we really have a usecase?
I agree that this is likely an XY problem.
So I challenge you to write an example where a given C++ expression of your choice appearing at a certain line of code is constexpr across one branch of execution and non-constexpr across another branch. And the branches can also be compile-time (well, given your question, you were not asking about non-compile-time branching, so in the previous sentence you can can also be are).

Why can't I use constexpr with lambda function?

I need an explanation for this. How does lambda differ from others function to it don't be allowed? Is this a nonsense to be not part of C++ standard? for example, I wanted to write a "nested" function in C++ but like it isn't possible to do directly I do use lambda instead of. This function does a very small job: take a single int parameter and multiply with some values and returns. This values are locals to where lambda function is defined and all them are constexpr and know at run-time for this reason I do want to let the compiler put a const value instead of call the function. It's very often used function (that's why I write this as function) and I don't want this beging computed at run-time.
It is because the standard list lambda as non constant expression : "5.19 Constant expressions" … "is a core constant expression unless it involves one of the following as a potentially evaluated subexpression" … "— a lambda-expression (5.1.2);"
That is enough for any compiler to reject constexpr function with a lambda involved.

Coverity reference function inputs for a custom checker

Is there a simple way to take the general arguments of a function (Pointer, Array, Integer) and get the values backing the expression, when writing a custom checker? As in, I match against a function such as:
Pointer p;
Integer i;
CallSite f("func");
if(MATCH( f(p,i) ))
//get function arguments
Is there a simple way of getting the values backing p and i? Thanks.
**Language is C++ to make a custom checker
There is no way to get run-time value from these variables statically.
Maybe it's more accurate to say that this is beyond the scope of what a simple static analysis checker can do.
The exception would be if you are passing a literal value or constant.

regular expression to rename pointer variables

I have this much
Code snippet:
int *filePointer;
float *valPtr;
*valPtr = 5.6;
filePointer = ∑
I would like to replace all pointer variables as follows, for example
*filePointer have to be converted to *filePointer_p.
filePointer have to be converted to filePointer.
valPtr have to be converted to valPtr_p
How can I do it using Regular Expression.
It sounds to me like you might be asking how to use regular expressions as a generic tool to rename all pointer variables in source code. I am assuming that the provided snippet is just an example.
If my understanding of your goal is correct, it is not possible to do that with regular expressions. A regular expression would not be able to determine reliably from the context if a variable is a pointer. Consider, for example, a=b;. a and b could be pointers or they could be most anything else. A regular expression by itself would not be able to determine that.
The first is simply:
s/\*filePointer/*filePointer_p/g
Not sure what you're second is on about? But if you're basically out to rename filePointer, then you should be able to simply do:
s/filePointer/filePointer_p/g
on the assumption that there aren't any other variables or context that contain the text filePointer in a different context.
For 1, try s/\*filePointer/*filePointer_p/g.