簡體   English   中英

模板中的名稱解析和實例化點

[英]Name resolution and Point of instantiation in Templates

這是ISO C ++標准14.6.4.1實例化點的聲明

 4.If a virtual function is implicitly instantiated, its point of instantiation
   is immediately following the point of instantiation of its enclosing
   class template specialization.

 5.An explicit instantiation directive is an instantiation point for the
   specialization or specializations specified by the explicit 
   instantiation directive.

 6.The instantiation context of an expression that depends on the
   template arguments is the set of declarations with external linkage 
   declared prior to the point of instantiation of the template 
   specialization in the same translation unit.

我無法為整個部分編寫程序。 我試圖從昨天開始為該部分編寫程序。

請,通常我會要求1分以上。 在任何部分。 但是在這里,我無法理解本節中的任何一點。

因此,任何人都可以為我提供本節要理解的代碼。

前兩個語句解釋了某些模板構造的實例化點在哪里; 它沒有引入新的模板構造。 因此,您可以重用之前的示例。

第三個語句(14.6.4.1/6)告訴我們實例化點的含義是:它們是在名稱查找的第二階段中查找名稱的點。 在實例化點之前聲明的名稱是可見的; 后來宣布的不是。 (在兩階段名稱查找的第一階段中,在模板定義之前的聲明集中查找非從屬名稱)。

因此,鑒於:

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

表達式T()+T()的實例化上下文是在foo<T>的各個實例化點之前的聲明集。 在這些上下文中會查詢名稱operator+ ,其中包括遵循該定義但在實例化點之前的聲明。

關於實例化上下文似乎總是有很多問題。

MSalters給出的示例有問題:

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

考慮以下代碼:

#include <iostream>

using namespace std;


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

class A {};

void operator +(const A&, const A&)
{
    cout << "Called operator+(const A&, const A&)" <<endl;
}

int main()
{
    foo<A>();
}

它可以編譯並在所有編譯器上運行,但是如果您將A類定義放入命名空間中:

#include <iostream>

using namespace std;


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

namespace {
   class A {};
}


void operator+(const A&, const  A&)
{
    cout << "operator+(const N::A&, const N::A&)" << endl;
}

int main()
{
     foo<A>();
}

Clang將無法編譯,但是VC ++和gcc會編譯。 為什么? 哪個編譯器符合規范?

坦白說,我不知道。 某些編譯器(例如gcc)甚至在此方面自相矛盾。 考慮以下代碼:

#include <iostream>

using namespace std;


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

namespace {
   class A {};
}


void g(A a)
{
    cout << "g(A)" << endl;
}

int main()
{
    foo<A>();
}

簡單地從“ operator +”更改為名為“ g”的函數,gcc無法編譯?為什么?

如果規范正確,那么為什么GCC找不到'g'?

6,依賴於模板參數的表達式的實例化上下文是具有外部鏈接的聲明集
在模板實例化點之前聲明
同一翻譯單元的專業化。

當我閱讀Bjarne Stroustrup的“ The C ++ Programming Language,第4版”,26.3.5模板和命名空間時,他有以下示例:

namespace N{
    class A{};
    char f(A);
}

char f(int);

template<typename T>
char g(T t)
{
    return f(t);       //choose f() depending on what T is
}

char f(double);

char c1 = g(N::A());   //causes N::f(N::A) to be called
char c2 = g(2);        //causes f(int) to be called
char c3 = g(2.1);      //causes f(int) to be called, f(double) not considered

在這里,f(t)很明顯是依賴的,因此我們不能在定義時綁定f。 為了生成g(N :: A)的特殊化,編譯器在名稱空間N中查找稱為f()的函數,並查找N :: f(N :: A)。

找到f(int)是因為它在模板定義點的范圍內。 找不到f(double),因為它在模板定義時不在范圍內,並且依賴於參數的查找找不到全局函數,該函數僅采用內置類型的參數。

真是一團糟!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM