#Overloading on consteval

46 messages · Page 1 of 1 (latest)

tribal osprey
#

Hi, I am dealing with a very unpleasant issue. I want to wrap compile-time known char arrays into a wrapper - and not-compile-time known strings into a different wrapper.

So, I would like to basically overload on if consteval

I was looking at the answer on SO here: https://stackoverflow.com/questions/76987078/is-it-possible-to-make-a-compile-time-evaluated-function-return-a-different-type

But it does not seem to actually work...
https://godbolt.org/z/fTvT8WT6W

So, my goal is to have an equivalent of:

template <size_t N>
wrapper1 foo(const char (&arg)[N]) { ... }

template <size_t N>
consteval wrapper2 foo(const char (&arg)[N]) { ... }

Is there any, standard or not, way to do it? I tried using __builtin_constant_p with no luck, as __builtin_choose_expr is not available in g++. Anything else failed so far

waxen lagoonBOT
#

When your question is answered use !solved or the button below to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

tribal osprey
#

@bronze marsh I saw you typing a bit, have you came up with anything?

bronze marsh
#

well, I think so, but why do you need this?

#

the unfortunate thing is that you still won't be able to tell a string literal from another kind of char array with this

tribal osprey
#

Not to copy string literals into temporary buffer when logging, since they live long enough

#

Basically, to detect things with program-long lifetime

bronze marsh
#

I would recommend using a UDL

#

oh OK

#

so this isn't actually about compile time constants but about lifetime

tribal osprey
#

Yeah... potato potato in this case, since I need it to outlive the thread

bronze marsh
#

yeah C++ unfortunately lacks a way to express this

#

rust can do it 😛

tribal osprey
#

I know! It does not help me in the slightest xD

bronze marsh
#

I guess you can do something like this:

#include <utility>

template <typename T>
struct comptime {
    T value;
    consteval comptime(auto&&... args) : value(std::forward<decltype(args)>(args)...) {}
};

template <typename T>
struct othertime {
    T value;
    othertime(auto&&... args) : value(std::forward<decltype(args)>(args)...) {}
};

void fun(comptime<int>);
void fun(othertime<int>);
#

ah

#

the ambiguity

#

yeah uh

#

that's rough

#

but it's also fundamentally not what you're actually looking for

#

so dunno

#

I think just using a UDL would be simplest

#

"bla"_static or smth

tribal osprey
#

I don't want to change 3000 existing calls T_T

bronze marsh
#

well

tribal osprey
#

time to write a paper to allow consteval overloading

#

Another function color yayyy

bronze marsh
#

;asm -std=c++23 -O3

#include <utility>

template <typename T>
struct comptime {
    T value;
    consteval comptime(auto&&... args) : value(std::forward<decltype(args)>(args)...) {}
};

template <typename T>
struct othertime {
    T value;
    othertime(auto&&... args) : value(std::forward<decltype(args)>(args)...) {}
};

void fun(comptime<int>);
void fun(othertime<int>, auto... no) requires (sizeof...(no) == 0);

void test(int x) {
    fun(42);
    fun(x);
}
mighty radishBOT
#
Compilation Errors
<source>: In function 'void test(int)':
<source>:20:9: error: call to consteval function 'comptime<int>(x)' is not a constant expression
   20 |     fun(x);
      |         ^
<source>:20:9:   in 'constexpr' expansion of 'comptime<int>(x)'
<source>:6:42: error: 'x' is not a constant expression
    6 |     consteval comptime(auto&&... args) : value(std::forward<decltype(args)>(args)...) {}
      |                                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bronze marsh
#

yeah uh

#

I don't think this is possible in standard C++ rn

#

I think just pattern search replace with a UDL might be the best option

versed plank
#

just because it uses the M-word I'd honestly prefer dot's suggestion, but since you mentioned non-standard, maybe something like this
https://godbolt.org/z/zxq4b4GYz

bronze marsh
#

I wish we had a way to declare a function parameter that must be initialized from a literal (and when it isn't then the function is just not a candidate, and when it is then that's a better match).

#

would help with a lot of things

#

but alas

tribal osprey
#

Wait, it is a function I can use in if constexpr? That's great

#

I had some issues with it some time ago, but I will try to make it work

#

One unfortunate thing is that this built-in behaves differently between clang and GCC - but that's not that important

#

It will only work as a macro, no?

bronze marsh
versed plank
#

I have no clue how you'd make it work as a non-macro, so I would say so

#

if you can't infer it within the function, can't make overload resolution work for it, then just force the call-site to figure it out

#

it just so happens that you make the call-site think it's using a function by injecting code in the call-site with a macro

tribal osprey
#

Such a dirty trick, love it! But I probably won't use it

versed plank
#

good, because I hate it
about the only place I've actually used that of stuff before is pre source_location source location
every time I'm considering my options between that kind of stuff, vs less ergonomic but "non-dirty" setups, I ponder how much alcohol it is reasonable to imbibe before pushing the code