Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 528
Cydouzo Avatar asked Dec 05 '19 06:12

Cydouzo


People also ask

Can you use const in C?

Variables can be declared as constant using the const keyword or the #define preprocessor directive.

How do you include a const in C++?

To declare a constant member function, place the const keyword after the closing parenthesis of the argument list. The const keyword is required in both the declaration and the definition.

How do you initialize a const member variable in a class?

To initialize the const value using constructor, we have to use the initialize list. This initializer list is used to initialize the data member of a class. The list of members, that will be initialized, will be present after the constructor after colon. members will be separated using comma.

When to use #define vs const?

The difference is that #define is processed by the preprocessor doing what amounts to simple text replacement. Const values defined like this are not visible for the actual compiler, while a variable defined with the const modifier is an actual typed "variable" (well not really that variable).

What is the use of const in C?

In C const is the keyword to create constants (variables which don’t change their value). Normally the usage of const is straightforward, but it becomes tricky when used with pointers. 30% Off my course, 30 days money back guarantee! The best place to start if you have no experience with programming:

How to define constants in C programming?

using a const keyword: Using const keyword to define constants is as simple as defining variables, the difference is you will have to precede the definition with a const keyword. Below program shows how to use const to declare constants of different data types: Refer Const Qualifier in C for details. This article is contributed by Chinmoy Lenka.

What is the difference between C++ 11 and C++ 14 constexpr?

In C++ 11, a constexpr function should contain only one return statement. C++ 14 allows more than one statement. constexpr function should refer only to constant global variables. constexpr function can call only other constexpr function not simple function.

What can you not use const constants for?

Constants can be numbers, Boolean values, strings, or a null reference. Don’t create a constant to represent information that you expect to change at any time. For example, don’t use a constant field to store the price of a service, a product version number, or the brand name of a company.


1 Answers

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 foos 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>{});
}
like image 81
Evg Avatar answered Sep 30 '22 15:09

Evg