提问人:Maestro 提问时间:10/26/2020 更新时间:10/26/2020 访问量:80
为什么在模板中,如果未实例化,我们可以在不声明的情况下使用依赖名称?
Why in a template we can use a dependent name without being already declared if not instantiated?
问:
我写了这段代码来理解名称查找: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
答:
请注意该错误输出中的行号。
您正在实例化第一个模板。第二个模板不是第一个模板的规范,而是一个函数模板,它需要一个不使用的模板参数。int
评论
file.cpp:128
file.cpp
在您的程序中,此定义:
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
相反,你实际上写了一个这样的专业化:foo
int
template <> // specialization of primary
void foo<int>(int i) // template foo with int
{
bar(i);
}
然后调用就可以了,因为它调用了专用化,并且 Lookup for 在此时确实找到了该名称。foo<int>(4);
bar
现在回到您的程序(没有专用化),例如,如果从未实例化,因为没有调用,会发生什么?好吧,程序仍然是错误的,但编译器可能不会告诉你。这是您用 和 描述的行为,这在形式上称为格式错误,不需要诊断。foo
print
do_it
评论
print(u)
实际上是不允许的。只是您不一定会收到错误消息。foo
template<> void foo<int>(int i);