Date: Tue, 29 Apr 2025 03:34:57 +0000
A more specific code:
#include <iostream>
#include <cstdint>
uint64_t myLog(uint64_t a, uint64_t b) {
if consteval (b) { // first judge whether b is constexpr
if (isPowerOfTwo(b)) { // then judge whether b is power of two
// Optimized implementation for b being compile-time known and a power of 2
return ...;
}
}
// Generic implementation
}
int main()
{
uint64_t a;
std::cin >> a;
std::cout << myLog(a, 2) << std::endl; // the parameter b (=2) is obviously constexpr, and will use the optimized implementation of myLog
return 0;
}
The parameter b (=2) is obviously constexpr, and the optimization for b being a power of 2 is performed only when b is constexpr (i.e., known to the compiler at compile time). If b is not constexpr, no special-case optimization is applied (using generic implementation), which aligns with the approach taken by most practical implementations.
And although the runtime test for "isPowerOfTwo" (conditional branch) will take a little time time in most cases, if the CPU's branch prediction fails and the pipeline is disrupted, it will incur significant overhead, in my opinion.
________________________________
From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Sent: Tuesday, April 29, 2025 11:18 AM
To: None <a1343922569_at_[hidden]>
Cc: marcinjaczewski86_at_[hidden] <marcinjaczewski86_at_gmail.com>; std-proposals_at_[hidden] <std-proposals_at_[hidden]>
Subject: Re: [std-proposals] Idea and proposal: Concise mechanism for detecting specific constexpr arguments within functions
On Mon, Apr 28, 2025 at 10:55 PM None <a1343922569_at_[hidden]<mailto:a1343922569_at_[hidden]>> wrote:
Thank you, Arthur, for your valuable feedback. I understand the technical challenges you pointed out, and indeed my original syntax if consteval(b) could have some problems
[snip more about syntax]
But it doesn't seem like you "understand the technical challenges I pointed out"! The issue isn't with the syntax. I actually like your first-choice syntax. The problem is:
Now, the big problem with this is that just knowing that `b`'s value is known to the compiler at compile-time — a boolean yes/no answer — doesn't give the programmer access to what numeric value the compiler thinks it has! [...]
One might say that the feature that is possible is not useful, while the feature that is useful is not possible.
Look at your own example again:
uint64_t myLog(uint64_t a, uint64_t b) {
if consteval (b) {
if (isPowerOfTwo(b)) {
// Optimized implementation for b being compile-time known and a power of 2
return ...;
}
}
// Generic implementation
}
The "if consteval (b)" line serves no purpose there. You could just as well have written:
uint64_t myLog(uint64_t a, uint64_t b) {
if (isPowerOfTwo(b)) {
// Optimized implementation for b being compile-time known and a power of 2
return ...;
}
// Generic implementation
}
Your "Optimized implementation" may have depended on b's value being a power of two, but it couldn't possibly have depended on b's value being compile-time known, since in fact you (as the programmer) do not know b's value, and the compiler has no mechanism to reveal it to you.
This example is also suboptimal because the runtime test for "isPowerOfTwo" can be done in about 2 machine instructions, so it's not as if we win big by skipping that test at runtime.
Maybe you can come up with a different (more motivating) example; but I doubt it.
–Arthur
#include <iostream>
#include <cstdint>
uint64_t myLog(uint64_t a, uint64_t b) {
if consteval (b) { // first judge whether b is constexpr
if (isPowerOfTwo(b)) { // then judge whether b is power of two
// Optimized implementation for b being compile-time known and a power of 2
return ...;
}
}
// Generic implementation
}
int main()
{
uint64_t a;
std::cin >> a;
std::cout << myLog(a, 2) << std::endl; // the parameter b (=2) is obviously constexpr, and will use the optimized implementation of myLog
return 0;
}
The parameter b (=2) is obviously constexpr, and the optimization for b being a power of 2 is performed only when b is constexpr (i.e., known to the compiler at compile time). If b is not constexpr, no special-case optimization is applied (using generic implementation), which aligns with the approach taken by most practical implementations.
And although the runtime test for "isPowerOfTwo" (conditional branch) will take a little time time in most cases, if the CPU's branch prediction fails and the pipeline is disrupted, it will incur significant overhead, in my opinion.
________________________________
From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Sent: Tuesday, April 29, 2025 11:18 AM
To: None <a1343922569_at_[hidden]>
Cc: marcinjaczewski86_at_[hidden] <marcinjaczewski86_at_gmail.com>; std-proposals_at_[hidden] <std-proposals_at_[hidden]>
Subject: Re: [std-proposals] Idea and proposal: Concise mechanism for detecting specific constexpr arguments within functions
On Mon, Apr 28, 2025 at 10:55 PM None <a1343922569_at_[hidden]<mailto:a1343922569_at_[hidden]>> wrote:
Thank you, Arthur, for your valuable feedback. I understand the technical challenges you pointed out, and indeed my original syntax if consteval(b) could have some problems
[snip more about syntax]
But it doesn't seem like you "understand the technical challenges I pointed out"! The issue isn't with the syntax. I actually like your first-choice syntax. The problem is:
Now, the big problem with this is that just knowing that `b`'s value is known to the compiler at compile-time — a boolean yes/no answer — doesn't give the programmer access to what numeric value the compiler thinks it has! [...]
One might say that the feature that is possible is not useful, while the feature that is useful is not possible.
Look at your own example again:
uint64_t myLog(uint64_t a, uint64_t b) {
if consteval (b) {
if (isPowerOfTwo(b)) {
// Optimized implementation for b being compile-time known and a power of 2
return ...;
}
}
// Generic implementation
}
The "if consteval (b)" line serves no purpose there. You could just as well have written:
uint64_t myLog(uint64_t a, uint64_t b) {
if (isPowerOfTwo(b)) {
// Optimized implementation for b being compile-time known and a power of 2
return ...;
}
// Generic implementation
}
Your "Optimized implementation" may have depended on b's value being a power of two, but it couldn't possibly have depended on b's value being compile-time known, since in fact you (as the programmer) do not know b's value, and the compiler has no mechanism to reveal it to you.
This example is also suboptimal because the runtime test for "isPowerOfTwo" can be done in about 2 machine instructions, so it's not as if we win big by skipping that test at runtime.
Maybe you can come up with a different (more motivating) example; but I doubt it.
–Arthur
Received on 2025-04-29 03:35:05