fetis
fetis

Reputation: 33

Can you conditionally remove a function parameter based on a template parameter?

my function looks like this

template<bool extra>
void func(int& arg1, const int arg2){
    //a lot of code...
    if (extra && arg2 > 0) ++arg1;
    arg1 *= 10;
    //a lot of code...
}

the problem is that when extra is false, arg2 is not used, but the function still requires it to be specified leading to unnecessary memory allocation for arg2 (you can check assembly output here). Is there any way to modify the function so that when extra is false, it only takes arg1, avoiding memory allocation for arg2 in that case?

Upvotes: 1

Views: 150

Answers (1)

ChrisB
ChrisB

Reputation: 3724

This kind of problem is commonly solved using template specialization, which unfortunately typically requires a wrapper struct instead of the plain functions.

Here's an example how that could work:

template<bool extra> // default case, only used for extra == false
struct Foo
{
    static void run(int arg1) {
        static_assert(extra == false);
        //...
    }
};
 
template<> //specialization, used for extra == true
struct Foo<true> 
{
    static void run(int arg1, const int arg2) {
        //...
    }
};

int main(){
    Foo<false>::run(1);
    Foo<true>::run(2, 3);
}

Depending on the desired API, you can sometimes create a wrapper function or use operator() to avoid the slightly ugly ::run calls.


In your specific example, where the signature of the two function version differs (because you don't expect arg2 for the extra == true case), you could even get away with basic function overloading:

// In this simple case you could even remove the template argument completely 
// and make the distinction purely based on the number of arguments.
// It all depends on what API you want to provide.
template<bool extra>
void func(int& arg1){
    static_assert(extra == false);
}
template<bool extra>
void func(int& arg1, const int arg2){
    static_assert(extra == true);
}

Note: If the template parameter should stay, a C++ 20 requires clause or enable_if guards instead of the static_asserts would express the intent of the function signature more accurately, currently at the cost of arguably worse error messages.

Upvotes: 3

Related Questions