C++ 模板实例化绑定在哪一点发生?
此代码来自Bjarne Stroustrup的“C++编程语言”(C.13.8.3实例化绑定点)C++ 模板实例化绑定在哪一点发生?,c++,templates,c++14,name-binding,template-instantiation,C++,Templates,C++14,Name Binding,Template Instantiation,此代码来自Bjarne Stroustrup的“C++编程语言”(C.13.8.3实例化绑定点) 模板 空隙f(T值) { g(价值); } 无效g(int v); void h() { 外接g(双); f(2); } 他提到: 这里,f()的实例化点就在h()之前,所以 在f()中调用的g()是全局的g(int),而不是局部的 g(双倍)。“实例化点”的定义意味着 模板参数永远不能绑定到本地名称或类 成员 void h() { struct X{};//局部结构 std::vector v;
模板
空隙f(T值)
{
g(价值);
}
无效g(int v);
void h()
{
外接g(双);
f(2);
}
他提到:
这里,f()的实例化点就在h()之前,所以
在f()中调用的g()是全局的g(int),而不是局部的
g(双倍)。“实例化点”的定义意味着
模板参数永远不能绑定到本地名称或类
成员
void h()
{
struct X{};//局部结构
std::vector v;//错误:无法将本地结构用作模板参数
}
我的问题是:
g()
稍后声明,我在g++4.9.2中确实遇到了一个错误,g
在这一点上没有声明f(2)
时,它会被实例化,这难道不合乎逻辑吗?就在我们称之为的地方,g(double)
已经在范围内了1985,C++程序的第一版发布,成为了语言的权威参考,因为<强>还没有正式的标准<强>。“所以C++ 11和C++ 14之间没有变化。我可以假设(请恕我直言)它在“预标准化”和标准化之间发生了变化。也许有人更了解C++的历史可以在这里揭示更多的东西。 至于实际发生的情况:
首先,让我们避开一个简单的问题:
extern g(double);
这是无效的C++。历史上,不幸的是C允许省略类型。在C++中,你必须编写代码>外部空格G(double)< /COD> .<
接下来,让我们忽略
g(double)
重载来回答您的第一个问题:
template <class T>
void f(T value)
{
g(value);
}
void g(int v);
int main()
{
f(2);
}
为了让任意名称g
顺利通过,我们有几个选项:
g
:g
与T
一起带入:X
(即全局名称空间)不在同一名称空间中,所以ADL找不到它
证明g
不在全局
int main()
{
void g(X);
X x;
g(x); // OK
::g(x); // ERROR
}
34:错误:全局命名空间中没有名为“g”的成员;你是说
简单地说是‘g’
1985,C++程序语言的第一版发布,成为了语言的权威参考,因为还没有正式的标准。“所以,在<代码> C++ 11 和<代码> C++ 14 之间没有变化。它在“预标准化”和标准化之间进行了更改。检查14.6.4.1[温度点]中的规则,并搜索两个阶段名称lookup@bolov我正在读第三版(1997)。谢谢你的回答。我有两个问题。1.为什么在第一个示例中
g
是非依赖的?它依赖于T(在本例中为int),使用ADL可以在定义了T的名称空间中找到它(就我所知,对于内置类型,名称空间应该是全局名称空间)。2.根据您的逻辑,为什么f(x)
可以工作,但是f(2)
不能与ADL一起工作?@user1289:f(2)
不能与ADL一起工作,因为2
是int
,这是一种基本类型,“1)对于基本类型的参数,相关的名称空间和类集是空的”(参见3.9.1基本类型)[basic.basical])@AndyG“依赖名称的绑定是通过查看依赖调用的参数名称空间中的名称来完成的(在内置类型的名称空间中考虑全局函数”-这是同一本书中的内容。@user1289:但是int
甚至没有引入全局函数。请参阅bolov关于在模板之前声明g
的部分。另外,我认为您应该读一本最近的书。您正在使用在C++03标准之前出版的一本书来问C++14个问题。我没有找到文档中的“对于基本类型的参数,相关的名称空间和类集为空”。尽管如您所述,f(2)不为我编译,而f(x)编译。
template <class T>
void f(T value)
{
g(value);
}
void g(int v);
int main()
{
f(2);
}
17 : error: call to function 'g' that is neither visible in the template definition nor found by argument-dependent lookup
g(value);
^
24 : note: in instantiation of function template specialization 'f<int>' requested here
f(2);
^
20 : note: 'g' should be declared prior to the call site
void g(int v);
void g(int);
template <class T>
void f(T value)
{
g(value);
}
template <class T>
void f(T)
{
T::g();
}
struct X {
static void g();
};
int main()
{
X x;
f(x);
}
template <class T>
void f(T value)
{
g(value);
}
struct X {};
void g(X);
int main()
{
X x;
f(x);
}
template <class T>
void f(T value)
{
g(value);
}
struct X{};
int main()
{
X x;
void g(X);
f(x);
}
int main()
{
void g(X);
X x;
g(x); // OK
::g(x); // ERROR
}