Home > Back-end >  Why even i am instantiating template parameter at runtime but i am getting expected output instead o
Why even i am instantiating template parameter at runtime but i am getting expected output instead o

Time:12-04

As I know that templates are expanded at compile time but in below example i am deciding or doing template instantiation at runtime depending on user input but still i am getting expected output.how this running? can someone explain me

#include <iostream>
using namespace std;

template<typename T>
class Demo
{
   T Value = 20.67;
   public:
    void print(T val)
    {
        std::cout << "value :" << val << std::endl;
    }

    T getValue()
    {
        return Value;
    }

};

int main()
{
    int a;
    std::cout << "Enter value for a :";
    std::cin >> a;
    if(a == 10)
    {
       Demo<int> demoObj1;
       demoObj1.print(demoObj1.getValue());
    }
    else
    {
       Demo<float> demoObj2;
       demoObj2.print(demoObj2.getValue());
    }
}

//output:

Enter value for a :10
value :20

and Enter value for a :7
value :20.67

CodePudding user response:

At compile time, both templates are created. There exists code in your compiled program for both branches. At runtime you are simply selecting which branch to execute.

The compiler sees the two branches of code and realizes that it cannot determine which branch will be taken at compile time, so it will generate code for both branches. If the compiler can determine at compile time that a branch cannot possibly be taken, a compiler may optimize it away. A simple situation is with the following:

if (4 < 5) {
   Demo<int> demoObj1;
   demoObj1.print(demoObj1.getValue());
} else {
   Demo<float> demoObj2;
   demoObj2.print(demoObj2.getValue());
}

In this case, the compiler can see that the second branch will never get executed. The compiler will initially compile both branches, but then it may discard the second branch from the final executable. Whether or not the compiler does this depends on the compiler implementation and compilation flags.

You can force the compiler to reject unused branches with if constexpr. Consider the following example:

if constexpr (4 < 5) {
   Demo<int> demoObj1;
   demoObj1.print(demoObj1.getValue());
} else {
   Demo<float> demoObj2;
   demoObj2.print(demoObj2.getValue());
}

All that was changed is that this example uses if constexpr. In this example, the second branch will NOT be fully compiled (it is still checked for correct syntax, but assembly generation is not done). Code for the second branch will not exist in the executable.

CodePudding user response:

Both Demo<int> and Demo<float> will be instantiated compile time as you're using a normal(non-constexpr) if, else instead of constexpr if.

On the other hand, if you were to use constexpr if then only one of Demo<int> or Demo<float> would've been instantiated. Note that in this example we can't use constexpr if since the input is taken from user.

  • Related