Home Item 20 - constexpr if (English)
Post
Cancel

Item 20 - constexpr if (English)

constexpr if

constexpr if is a new syntax introduced in C++17, allowing compile-time selection based on conditions, thus avoiding the need for template specialization and SFINAE techniques often used in template metaprogramming.

SFINAE stands for “Substitution Failure Is Not An Error,” which is a technique in C++ template metaprogramming. When instantiating templates, if there is an error in deducing template parameters or performing template specialization, SFINAE allows the compiler to continue template instantiation rather than reporting an error.

However, this feature can make your code difficult to read. Let’s look at some code examples.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// Define a function template specialized based on the type T, for handling integer data
template<typename T>
void process_data(const T& data) {
    std::cout << "Unknown type of data" << std::endl;
}

// Template specialization for handling integer data
template<>
void process_data<int>(const int& data) {
    std::cout << "Integer data: " << data << std::endl;
}

// Template specialization for handling floating-point data
template<>
void process_data<float>(const float& data) {
    std::cout << "Floating-point data: " << data << std::endl;
}

// Template specialization for handling string data
template<>
void process_data<std::string>(const std::string& data) {
    std::cout << "String data: " << data << std::endl;
}

int main() {
    std::string str = "Hello";
    process_data(10);        // Integer data
    process_data(3.14f);     // Floating-point data
    process_data(str);       // String data
    process_data(true);      // Unknown type of data
    return 0;
}

Using constexpr if

The code becomes much simpler and easier to read

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Define a function template that performs different operations based on the type T at compile time
template<typename T>
void process_data(const T& data) {
    // Use constexpr if to choose based on the type T at compile time
    if constexpr (std::is_integral<T>::value) {
        std::cout << "Integer data: " << data << std::endl;
    }
    else if constexpr (std::is_floating_point<T>::value) {
        std::cout << "Floating-point data: " << data << std::endl;
    }
    else if constexpr (std::is_same<T, std::string>::value) {
        std::cout << "String data: " << data << std::endl;
    }
    else {
        std::cout << "Unknown type of data" << std::endl;
    }
}

int main() {
    std::string str = "Hello";
    process_data(10);        // Integer data
    process_data(3.14f);     // Floating-point data
    process_data(str);       // String data
    process_data(true);      // Unknown type of data
    return 0;
}

Result

Desktop View

In this example, the reason why the output of process_data(true) is “unknown type data” in the version using template specialization, while it is “integer type data” in the version using constexpr if, is because these two methods handle conditionals differently.

In the version using template specialization, we have defined specialized versions for integer, floating-point, and string types, but not for boolean type. Therefore, when process_data(true) is called, the compiler looks for a specialization related to boolean type but cannot find a corresponding one, so it uses the generic template version, resulting in “unknown type data” output.

On the other hand, in the constexpr if version, we use if constexpr for conditional evaluation, choosing different code paths based on the condition. In this case, the condition is std::is_integral::value, which checks if type T is an integer type. When T is a boolean type, std::is_integral::value returns true, so the code path inside the if `constexpr` block is selected, leading to the "integer type data" output.

Copy the code and run it to see the results! This will provide a clearer understanding of what was discussed above. Happy coding!

☝ツ☝

This post is licensed under CC BY 4.0 by the author.

👈 ツ 👍