Proposal "is_constexpr"

277 views
Skip to first unread message

dime...@gmail.com

unread,
Jul 17, 2017, 6:15:53 AM7/17/17
to ISO C++ Standard - Future Proposals
□ Motivation
In C++, the same semantic functions sometimes have to write two different versions, a constexpr version, an efficient general version.
For example:
constexpr auto StrLen(const char *s) {auto tp=s;while(*s) s++;return s-tp;}
auto StrLenSSE4(const char *s){...}
□ Proposal
Gcc has a built-in function __builtin_constant_p (v) to determine whether a value is a compile time constant, but it can only be used for macros, and v can only be one literal.
Can you provide a function of is_constexpr(v) to determine whether v is a compile time constant?
In this way, the function above can use a unified interface.
constexpr auto StrLen(const char *s){
  if constexpr(is_constexpr(s)) {
    auto tp=s;while(*s) s++;return s-tp;
  }
  else return StrLenSSE4(s);
}

Daemon Snake

unread,
Jul 17, 2017, 11:14:05 AM7/17/17
to std-pr...@isocpp.org
Hi,

is_constexp(s) is not possible, nor likely currently as function arguments are never constexpr.
The subject is highly controversial (possible ODR violations, etc...).




--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/803a7b14-34c2-4ee6-8c5a-154532143a6e%40isocpp.org.

Nicol Bolas

unread,
Jul 17, 2017, 11:14:50 AM7/17/17
to ISO C++ Standard - Future Proposals
I know there are a lot of papers out there. But does it really take that long to search them for "constexpr" to see if this has already been proposed? You can even do a Google site-specific search to just search WG21's papers.

And, as shown in that paper, checking for the `constexpr` status of a variable is rather pointless. What you really want to ask is "is this code being run at compile-time?"

T. C.

unread,
Jul 17, 2017, 4:48:53 PM7/17/17
to ISO C++ Standard - Future Proposals
Gcc has a built-in function __builtin_constant_p (v) to determine whether a value is a compile time constant, but it can only be used for macros, and v can only be one literal.

That's so not how __builtin_constant_p works.

Erich Keane

unread,
Jul 17, 2017, 6:27:49 PM7/17/17
to ISO C++ Standard - Future Proposals
In Kona, Daveed proposed this: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0595r0.html

it made it through EWG, and seems to accomplish your goal.  Additionally, since "is_constexpr" is a compile-time constant, the constant folder level of optimization will just 'fix' it for the 'false' case.

BTW: No progress was made by Daveed in Toronto, but no idea if that was on purpose, or just a ball dropped.

Pedro Alves

unread,
Jul 18, 2017, 9:20:40 AM7/18/17
to std-pr...@isocpp.org
On 07/17/2017 11:15 AM, dime...@gmail.com wrote:
> □ Motivation
> In C++, the same semantic functions sometimes have to write two
> different versions, a constexpr version, an efficient general version.
> For example:
> constexpr auto StrLen(const char *s) {auto tp=s;while(*s) s++;return s-tp;}
> auto StrLenSSE4(const char *s){...}
> □ Proposal
> Gcc has a built-in function __builtin_constant_p (v) to determine
> whether a value is a compile time constant, but it can only be used for
> macros, and v can only be one literal.
> Can you provide a function of *is_constexpr*(v) to determine whether v
> is a compile time constant?
> In this way, the function above can use a unified interface.
> constexpr auto StrLen(const char *s){
> if constexpr(*is_constexpr*(s)) {
> auto tp=s;while(*s) s++;return s-tp;
> }
> else return StrLenSSE4(s);
> }

Note that GCC's __builtin_constant_p _can_ be used for the
above. It's how C++17 constexpr char_traits<>::length() etc.
is currently implemented in libstdc++ trunk. (BTW, you can
just use char_traits<>::length() in this case.)

#include <string.h>

static constexpr bool
constant_string_p(const char* s)
{
while (__builtin_constant_p(*s) && *s)
s++;
return __builtin_constant_p(*s);
}

static constexpr size_t constexpr_strlen(const char* s)
{
auto tp = s;
while (*s)
s++;
return s - tp;
}

constexpr size_t my_strlen(const char* s) noexcept
{
if (constant_string_p(s))
return constexpr_strlen(s);
return strlen(s);
}

static_assert (my_strlen ("") == 0);
static_assert (my_strlen ("hello") == 5);
static_assert (my_strlen ("he\0llo") == 2);

static const char array[] = "foo";
static_assert (my_strlen (array) == 3);

constexpr bool check()
{
char s[] = "str";
s[0] = 'l';
s[1] = '\0';
return my_strlen(s) == 1;
}

static_assert(check());

int main (int argc, char** argv)
{
return my_strlen(argv[0]);
}

$ g++ constexpr_strlen.cc -o constexpr_strlen -g3 -O2 -std=gnu++17
$ gdb --batch -q ./constexpr_strlen -ex "disassemble main"
Dump of assembler code for function main(int, char**):
0x00000000004004c0 <+0>: sub $0x8,%rsp
0x00000000004004c4 <+4>: mov (%rsi),%rdi
0x00000000004004c7 <+7>: callq 0x400490 <strlen@plt>
0x00000000004004cc <+12>: add $0x8,%rsp
0x00000000004004d0 <+16>: retq
End of assembler dump.
$
Reply all
Reply to author
Forward
0 new messages