简体   繁体   中英

C++ 11, how to use a const inside an #if

I use a const variable in my code. And would like to tell my pre-processor to use it. Namely:

const double x = 1.2;
const bool xIsZero = x==0;

#if xIsZero
...
#endif

But that doesn't work. In C++ 17, if constexpr doest the trick. But I'm stuck with C++11 for now.

So instead I could use a workaround like:

#define X 1.2
#define xIsZero (x==0)
const double x = X;

#if xIsZero
...
#endif

But I just dislike giving x to a #define, I'd like to give it directly to a const. Is there a way to do that?

If the condition is known at compile-time, you can use overloading to mimic if constexpr in C++11:

void foo(std::true_type) {   // if (xIsZero)
}

void foo(std::false_type) {  // if (!xIsZero)
}

constexpr bool xIsZero = ...;
foo(std::integral_constant<bool, xIsZero>{});

As LoPiTaL noted in comments, this is not fully equivalent to if constexpr , because both foo s have to compile. This technique becomes important when we work with templates. With plain if both branches are compiled with the same set of template parameters. With overloading we can effectively discard branches.

For example, this code fails:

template<unsigned int i>
void foo(std::integral_constant<unsigned int, i>) {
    if (i > 0) {
        consume_positive_i(i);
        foo(std::integral_constant<unsigned int, i - 1>{});
    } else
        consume_zero_i(i);
}

In C++17 it can easily be fixed with if constexpr :

template<unsigned int i>
void foo(std::integral_constant<unsigned int, i>) {
    if constexpr (i > 0) {
        consume_positive_i(i);
        foo(std::integral_constant<unsigned int, i - 1>{});
    } else
        consume_zero_i(i);
}

The workaround in C++11 is overloading:

void foo(std::integral_constant<unsigned int, 0>) {   
    consume_zero_i(i);
}

template<unsigned int i>
void foo(std::integral_constant<unsigned int, i>) {
    consume_positive_i(i);
    foo(std::integral_constant<unsigned int, i - 1>{});
}

#if statement is a preprocessor directive. Preprocessor works with your code before the process of compilation. Preprocessor even doesn't know what your code mean, it actually works with text. '#if' checks if argument is true (or defined) and put code into file from #if - #else - #endif statement.

#define replaces your code for selected. And when you type

#define X 1.2
void f() {
    if(X == 0) //...
}

Preprocessor replace this for the

void f() {
    if(1.2 == 0) //...
}

const is a keyword for compiler. Constants are defined in the time of compilation and they are put into special area in memory. So when you type

const double x = 1.2;
void f () {
    if(x == 0) //...
}

you call x from that memory.

So when you're trying to access with preprocessor to the area that compiler deal with, you're getting what you have.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM