c++ 为什么即使我在运行时示例化模板参数,但我得到的是预期的输出而不是错误,即我们不能在运行时扩展模板?

mo49yndu  于 2022-12-05  发布在  其他
关注(0)|答案(2)|浏览(93)

正如我所知,模板是在编译时扩展的,但在下面的例子中,我决定或做模板示例化在运行时取决于用户输入,但我仍然得到预期output.how这运行?有人能解释我吗

#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());
    }
}

//输出:
输入a的值:10
数值:20
并输入a的值:7
数值:20.67

u0njafvf

u0njafvf1#

在编译时,两个模板都被创建。在编译的程序中存在两个分支的代码。在运行时,您只需选择要执行的分支。
编译器会看到代码的两个分支,但意识到它无法在编译时确定执行哪个分支,因此它会为两个分支都生成代码。如果编译器在编译时确定某个分支不可能被执行,编译器可能会将其优化掉。下面是一个简单的情况:

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

在这种情况下,编译器可以看到第二个分支永远不会被执行。编译器最初会编译两个分支,但随后可能会从最终的可执行文件中丢弃第二个分支。编译器是否这样做取决于编译器的实现和编译标志。
可以使用if constexpr强制编译器拒绝未使用的分支。

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

所做的更改只是此示例使用if constexpr。在此示例中,第二个分支将不会完全编译(仍会检查语法是否正确,但不会生成程序集)。第二个分支的代码将不存在于可执行文件中。

vmdwslir

vmdwslir2#

Demo<int>Demo<float>都将在编译时示例化,因为您使用的是普通的(非常量表达式)if,else而不是constexpr if
另一方面,如果你使用constexpr if,那么只有Demo<int>Demo<float>中的一个会被示例化。注意,在这个例子中我们不能使用constexpr if,因为输入来自用户。

相关问题