Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 模板实例化绑定在哪一点发生?_C++_Templates_C++14_Name Binding_Template Instantiation - Fatal编程技术网

C++ 模板实例化绑定在哪一点发生?

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;

此代码来自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;//错误:无法将本地结构用作模板参数
}
我的问题是:

  • 为什么第一个代码可以工作
    g()
    稍后声明,我在g++4.9.2中确实遇到了一个错误,
    g
    在这一点上没有声明

  • 外部g(双重)-这是如何工作的?因为在函数重载的情况下返回值并不重要,所以在前向声明中我们可能会错过它

  • f()的实例化点就在h()之前-为什么?当调用
    f(2)
    时,它会被实例化,这难道不合乎逻辑吗?就在我们称之为的地方,
    g(double)
    已经在范围内了

  • “实例化点”的定义意味着模板参数永远不能绑定到本地名称或类成员-这在C++14中改变了吗?我在C++(G++4.9.2)中遇到了错误,但在C++14(G++4.9.2)中没有遇到错误


  • 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
  • 通过ADL将
    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
    }