2

I'm trying to hiper-optimize a code and i find that the program would run like 10% faster if i separate an action in 2 parts in case the programer want to run the method in true or false, so i tried to do this:

template<bool way> void action(){
    #if way
    cout << "Do true actions" << endl;
    #else
    cout << "Do false actions" << endl;
    #endif // way
}

int main()
{
    action<true>();
    action<false>();
    return 0;
}

But of course when i compile this code it prints:

Do false actions
Do false actions

Of course a way to do this would be do 2 different functions but in my code this would significantly increase the number of functions just for one boolean. So, how can i do this? (Pass arguments of a template to a preprocessor #if)

  • 2
    It can't be done. C++ does not work this way, at a fundamental level. In C++17 one can use `if constexpr` to achieve the same result, so you need a modern C++ compiler that supports C++17. It will also be helpful to read up a little bit more of your C++ book, specifically the chapter that explains what a preprocessor is and how it works, specifically that source is preprocessed before anything else, so the preprocessor has no clue about any templates, functions, or code. – Sam Varshavchik Aug 25 '19 at 02:33
  • A `if constexpr` of course! Thank you – Alexander Vladimirovich Aug 25 '19 at 02:35
  • 1
    Why do you avoid two functions, if the code as demonstrated has no common parts? Could you change the example to demonstrate the desired benefit of doing it in one functions? The `template void action(){` just wants to be solved with separate specialisations for true/false. I actually had an answer like that, but now want to understand the one function requirement. Would one function with two specialisations be an acceptable solution? – Yunnosch Aug 25 '19 at 06:54

2 Answers2

1

How do I make the preprocessor take template parameters?

Sorry, but no. You can't do that.

So, how can I do this?

Alternatively C++ does give you a way to do exactly that, called SFINAE, which lets you evaluate code at compile time, like this:

template<bool way>
std::enable_if_t<way> action()
{
    std::cout << "Do true actions\n";
} 

template<bool way>
std::enable_if_t<!way> action()
{
    std::cout << "Do false actions\n";
} 

int main()
{
    action<true>();
    action<false>();
}

In C++17, you can use if constexpr, which is equivalent to the previous example above, but more expressive and intuitive:

template<bool way>
void action()
{
    if constexpr (way)
    {
        std::cout << "Do true actions\n";
    }
    else
    {
        std::cout << "Do false actions\n";
    }
} 
Dean Seo
  • 5,486
  • 3
  • 30
  • 49
1

Mixing pre-processor and C++ is usually not the way to go.
You can introduce a template with a bool parameter and then specialise for true and false.

#include <iostream>

using namespace std;

template<bool way> void action(void)
{
    cout << "neither true nor false" << endl;
    // does not get called, not even for "2",
    // because bool ensures false or true
}

template<> void action<false>(void)
{
    cout << "false" << endl;
}

template<> void action<true>(void)
{
    cout << "true" << endl;
}

int main()
{
    action<false>();
    action<true>();
    action<2>(); // true, forced by using bool instead of int as parameter
    return 0;
}

Output:

false
true
true

Yunnosch
  • 26,130
  • 9
  • 42
  • 54