0

我编写了这段代码来理解template名称查找:

//void bar(int);

template <typename T>
void foo(T x)
{
    bar(x);
}

void bar(int x)
{
    std::cout << "bar(int)\n";
}

template <int>
void foo(int i)
{
    bar(i);
}



int main()
{

    foo<int>(4);


    std::cout << "\ndone!\n";
}

bar(int)故意注释掉了函数的声明。此函数bar(int)用作dependent name模板函数中的一个foo。所以它受实例化的约束。

  • 我已经在专业化bar之后foo和之前进行了定义,foo<int>以便后者可以看到bar(int).

但是当我编译代码时,我得到了这个错误:

‘bar’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]|. 如果我取消注释bar(int)它的声明工作正常?!

  • 如果我必须在模板中将其用作从属名称之前声明一个名称,那么为什么 C++ 允许在未实例化的情况下使用它。(如果我不“使用”模板化函数,代码是否有效foo)?

      template <typename U>
      void do_it(U u)
      {
          print(u); // not bound until instantiation
      }
    

那么允许调用尚未声明并且在实例化时会失败print(u)的想法是什么?do_it

4

2 回答 2

3

在您的程序中,此定义:

template <int>     // not a specialization, just a different
void foo(int i)    // template with a non-type template parameter
{
    bar(i);
}

实际上并没有定义foo主模板的特化。因此,当您拨打此电话时:

Foo<int>(4);

你最终调用了主模板。查找名称bar未找到该名称,您会收到错误消息。

相反,您实际上编写了这样的foofor特化int

template <>           // specialization of primary
void foo<int>(int i)  // template foo with int
{
    bar(i);
}

那么调用foo<int>(4);就可以了,因为它调用了专业化,并且bar在那时查找确实找到了该名称。


现在回到您的程序(没有专门化),如果foo从未实例化会发生什么,例如因为没有调用?好吧,程序仍然是错误的,但编译器可能不会告诉你。这是您使用print和描述的行为,do_it这正式称为格式错误,不需要诊断

于 2020-10-25T21:36:30.413 回答
1

请注意该错误输出中的行号。

您正在实例化第一个模板。第二个模板不是第一个模板的规范,而是一个需要int它不使用的模板参数的函数模板。

于 2020-10-25T21:31:38.680 回答