Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can C++ templates be used for conditional code inclusion?

Tags:

c++

templates

So that:

template <bool Mode>
void doIt()
{
   //many lines
   template_if(Mode)
   {
      doSomething(); // and not waste resources on if
   }
   //many other lines
}

I know there is enable_if command that can be used for enabling the function conditionally, but I do not think I can use it such option here. Essentially what I need is template construct that acts as #ifdef macro.

like image 276
Draif Kroneg Avatar asked May 05 '16 10:05

Draif Kroneg


2 Answers

Before trying something complex it's often worth checking if the simple solution already achieves what you want.

The simplest thing I can think of is to just use an if:

#include <iostream>

void doSomething()
{
  std::cout << "doing it!" << std::endl;
}

template <bool Mode>
void doIt()
{
   //many lines
   if(Mode)
   {
      doSomething(); // and not waste resources on if
   }
   //many other lines
}

void dont()
{
  doIt<false>();
}

void actuallyDoIt()
{
  doIt<true>();
}

So what does that give:

gcc 5.3 with no optimizations enabled gives:

void doIt<false>():
    pushq   %rbp
    movq    %rsp, %rbp
    nop
    popq    %rbp
    ret
void doIt<true>():
    pushq   %rbp
    movq    %rsp, %rbp
    call    doSomething()
    nop
    popq    %rbp
    ret

Note no doSomething() call in the false case just the bare work of the doIt function call. Turning optimizations on would eliminate even that. So we already get what we want and are not wasting anything in the if. It's probably good to leave it at that rather than adding any unneeded complexity.

like image 142
PeterSW Avatar answered Sep 29 '22 18:09

PeterSW


It can sort of be done.

If the code inside your "if" is syntactically and semantically valid for the full set of template arguments that you intend to provide, then you can basically just write an if statement. Thanks to basic optimisations, if (someConstant) { .. } is not going to survive compilation when someConstant is false. And that's that.

However, if the conditional code is actually not valid when the condition isn't met, then you can't do this. That's because class templates and function templates are instantiated ... in full. Your entire function body is instantiated so it all has to be valid. There's no such thing as instantiating an arbitrary block of code.

So, in that case, you'd have to go back to messy old function specialisation with enable_if or whatever.


C++17 is likely to have if constexpr which essentially gives you exactly this. But that's future talk.

like image 34
Lightness Races in Orbit Avatar answered Sep 29 '22 18:09

Lightness Races in Orbit