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

Time:08-29

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?

CodePudding user response:

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.

CodePudding user response:

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.

  •  Tags:  
  • c
  • Related