Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
219 views
in Technique[技术] by (71.8m points)

Standard way to enforce constexpr for parts of complex expression in C++?

Sometimes there is a need to enforce computation of some expression at compile time.

E.g. if we have f(/*some args*/) function that is constexpr, it can be computed both at compile and run time. But if we want to force it to be compile-time one way is to assign its value to constexpr constant:

constexpr auto x = f(/*some args*/);

But what to do if we want it to be used as a part of complex expression, whole expression can be run-time value, but it is interesting sometimes to compute some parts of expression at compile time if it gives some noticeable performance improvements (or for other reasons stated below). E.g. expression:

int x = 123;
int y = x + 456 * f(/*some args*/);

In the expression above one way to enforce compile time computation of f is to use std::integral_constant:

int x = 123;
int y = x + 456 * std::integral_constant<int, f(/*some args*/)>::value;

But maybe there is some shorter way to do it in standard C++? E.g. maybe there is a kind of constexpr operator: 456 * constexpr(f(/*some args*/))?

The shortest form I figured out:

template <auto V>
constexpr inline auto ce = V;


int y = x + 456 * ce<f(/*some args*/)>;

This solution is nice, but maybe there is already similar to ce<...> templated constant inside standard C++ library? So that I don't invent new classes/functions if there are some standard ones. Because current standard class std::integral_constant needs specifying type as first argument and also needs ::value, which is not very short way to write.

Why do I bother about enforcing compile time? Because of next code:

Try it online!

struct S {
    consteval bool has42() const {
        return i == 42;
    }
    int i = 0;
};

template <auto V>
constexpr inline auto ce = V;

int main() {
    constexpr S s;
    int z = 10;
    auto x = z + int(ce<s.has42()>); // OK
    auto y = z + int(s.has42()); // Compile error
}

Code above works perfectly well under CLang, but under latest MSVC line with auto y.... doesn't compile with error error C7595: 'S::has42': call to immediate function is not a constant expression. Line with auto x..... compiles correctly on both CLang/MSVC due to use of ce<...> which enforces compile time computation.

Seems that MSVC supposes all expressions to be run-time values if they are not stated as constexpr explicitly. Of cause although they are marked as run-time values still compiler does all optimizations and probably compile time code will not be different from run-time.

question from:https://stackoverflow.com/questions/65936269/standard-way-to-enforce-constexpr-for-parts-of-complex-expression-in-c

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...