Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constexpr if alternative

Tags:

I would like to use constexpr if to branch at compile time, but it does not seem to be supported by the latest MSVC compiler. Is there an alternative to the following?:

template<typename T> void MyFunc() {     if constexpr(MeetsConditions<T>::value)     {         FunctionA<T>();     }     else     {         FunctionB<T>();     } } 

In short: Can I simulate constexpr if when it is not supported by the compiler?

like image 244
Aart Stuurman Avatar asked Apr 24 '17 11:04

Aart Stuurman


People also ask

Can constexpr use if?

constexpr if enables it to conditionally compile source code and can also be used for nice tricks at compile time.

Does constexpr improve performance?

constexpr is a feature added in C++ 11. The main idea is a performance improvement of programs by doing computations at compile time rather than run time.

Why is constexpr needed?

A constexpr integral value can be used wherever a const integer is required, such as in template arguments and array declarations. And when a value is computed at compile time instead of run time, it helps your program run faster and use less memory.

What is false constexpr?

In a constexpr if statement, the value of condition must be a contextually converted constant expression of type bool. If the value is true, then statement-false is discarded (if present), otherwise, statement-true is discarded.


2 Answers

One of pre-C++17 ways is to use partial template specializations, like here:

template <typename T, bool AorB> struct dummy;  template <typename T, true> struct dummy {     static void MyFunc() {  FunctionA<T>(); } }  template <typename T, false> struct dummy {     static void MyFunc() {  FunctionB<T>(); } }  template <typename T> void Facade() {     dummy<T, MeetsConditions<T>::value>::MyFunc(); } 

If you need more, than 2 specializations - you can use enum or integral value, and make specializations for all needed enums.

Another way is to use std::enable_if:

template <typename T> std::enable_if<MeetsConditions<T>::value, void>::type MyFunc() {    FunctionA<T>(); }  template <typename T> std::enable_if<!MeetsConditions<T>::value, void>::type MyFunc() {    FunctionB<T>(); } 
like image 155
Starl1ght Avatar answered Oct 04 '22 23:10

Starl1ght


You can do it the old fashioned, tried and tested tag dispatch way:

template<typename T> void MyFuncImpl(std::true_type) {   FunctionA<T>(); }  template<typename T> void MyFuncImpl(std::false_type) {   FunctionB<T>(); }  template<typename T> void MyFunc() {   MyFuncImpl<T>(std::integral_constant<bool, MeetsConditions<T>::value>{}); } 
like image 43
StoryTeller - Unslander Monica Avatar answered Oct 04 '22 23:10

StoryTeller - Unslander Monica