Шаблоны: Разрешение имен: Точка создания: -> Кто-нибудь может рассказать еще несколько примеров для этого утверждения? - PullRequest
4 голосов
/ 28 сентября 2010

Это утверждение из стандарта ISO C ++ 14.6.4.1 Точка создания

  1. Для специализации шаблона функции, специализации шаблона функции-члена или специализации для членафункция или статический член данных шаблона класса, если специализация создается неявно, так как на нее ссылаются из другой специализации шаблона, а контекст, на который она ссылается, зависит от параметра шаблона, то точка конкретизации специализации является точкойконкретизация вмещающей специализации.В противном случае точка создания такой специализации сразу следует за объявлением или определением области пространства имен, относящимся к специализации.

  2. Если шаблон функции или функция-член шаблона класса вызывается вспособ, который использует определение аргумента по умолчанию для этого шаблона функции или функции-члена, точка создания аргумента по умолчанию - это точка создания шаблона функции или специализации функции-члена.

  3. Для специализации шаблона класса, специализации шаблона элемента класса или специализации для члена класса шаблона класса, если специализация неявно создается, поскольку на нее ссылаются из другой специализации шаблона, если контекст, из которого эта специализацияссылка зависит от параметра шаблона, и если специализация
    не была создана до создания шаблона, точка iСоздание непосредственно перед точкой создания вложенного шаблона.В противном случае точка
    создания экземпляра для такой специализации непосредственно предшествует объявлению или определению области пространства имен, относящемуся к специализации.

Я не могу написать программы длявесь этот раздел.Со вчерашнего дня я пытаюсь написать программы для этого раздела.

Может ли кто-нибудь предоставить мне код для этих разделов, чтобы понять.

Пожалуйста, обычно .. Я пытался задать 1 илибольше очков.В любом разделе.Но здесь я не могу понять ни единой точки в этом разделе.

Так что любезно может предоставить мне код (программы) для понимания этих разделов.

Ответы [ 2 ]

5 голосов
/ 29 сентября 2010

Я нахожу это утомительным занятием, и у комитета есть больше таких забав . Поэтому я думаю, что, вероятно, у меня есть некоторые ошибки в ниже. Поэтому, пожалуйста, прочитайте внимательно:)

Третий абзац

Для специализации шаблона класса, специализации шаблона члена класса или специализации для члена класса шаблона класса, если специализация создается неявно, потому что на нее ссылаются из другой специализации шаблона, если контекст, из которого специализация Ссылка зависит от параметра шаблона, и если специализация не была создана до создания экземпляра вмещающего шаблона, точка создания экземпляра находится непосредственно перед точкой создания вмещающего шаблона.

Другими словами, если создается экземпляр шаблона класса или вложенного класса шаблона класса, а контекст, вызывающий создание этого экземпляра, зависит от параметра шаблона, то экземпляр шаблона / вложенного класса создается непосредственно перед точкой создания экземпляра класса. Шаблон, который ссылается на это.

Контекст в другой специализации может зависеть от параметров шаблона, как в случае первичных шаблонов, частичных специализаций и членов шаблона класса, или он не зависит от параметров шаблона, который случай для ссылок изнутри явных специализаций.

В противном случае [т.е. контекст не зависит], точка создание такой специализации непосредственно предшествует объявлению или определению области пространства имен, относящемуся к специализации.

Это различие важно. Подумайте, что произойдет, если точка создания экземпляров для специализаций из зависимых контекстов будет предшествовать немедленному объявлению или определению области имен пространства имен

template<typename T, int N> 
struct A {
  typedef typename A<T, N-1>::type *type;
};

template<typename T>
struct A<T, 0> {
  typedef T type;
};

typedef A<int, 2>::type ptr;

Этот шаблон должен добавить N деклараторов указателей. Например, A<int, 2> равно int**.

  • Контекст вокруг typedef A<int, 2>::type не зависит, поэтому A<int, 2> создается перед объявлением typedef.
  • В пределах A<int, 2> у нас есть A<int, N-1>::type, который появляется в зависимом контексте и который ссылается на A<int, 1>::type. Таким образом, Стандарт требует от нас создания экземпляра A<int, 1> в тот же момент, что и экземпляр A<int, 2>.

    Если бы мы создали бы это непосредственно перед объявлением области имен пространства имён, которое ссылалось на него (до определения основного шаблона), мы бы не заметили частичную специализацию A<T, 0> при обработке `A<int, N-1>::type в пределах A<int, 1> потому что мы бы создали A<int, 1> до этой специализации.

Второй абзац

Это просто для того, чтобы имена, найденные в аргументах по умолчанию, соответствовали именам, найденным в остальной части функции, для которой они используются (т.е. их POI совпадает с POI их шаблона функции / функции-члена класса). шаблон).

Первый абзац

Это в основном то же самое, что и третий абзац. Тем не менее, шаблоны функций создаются после сущности, которая ссылается на них, так что возможно рекурсивное использование, как в следующем примере. Напротив, шаблоны классов создаются перед объектом, который ссылается на них, потому что объект требует, чтобы этот тип класса был завершенным. Если POI типа класса будет после этой сущности, тип класса все равно не будет существовать.

template<typename T>
void f(T);

template<typename T>
struct A {
  void g() {
    f(0);
  }

  void h() { /* do a dance */ }
};

template<typename T>
void f(T t) {
  A<T> a;
  a.h();
}

void g() {
  A<int> a; 
  a.g();
}

Если f будет создан до A<int>, то он не сможет получить доступ к a.h(), поскольку на тот момент он еще не существовал. Поэтому шаблоны функций создаются после сущности, которая на них ссылается, а шаблоны классов создаются перед сущностью, которая на них ссылается.

0 голосов
/ 28 сентября 2010

Попросите кого-нибудь исправить мое понимание ...

Я думаю, что приведенный ниже код иллюстрирует, что означают 1 и 2 (из того, что я понял):

template<class T> void f1(T t){cout << 0;} 

template<class T> void f2(T t, void (*p)(int) = f1){
   (*p)(0);
} 

void f(double d){cout << 1;} 

template<class T> void g(T t){ 
    f1(t);            // this is the interesting call. 
} 

void f1(int t){cout << 2;} 

int main(){ 
    g(2); 
    f2(2);
}     // POI for f1(t), Also POI for f2(2)

Рассмотрим вызов g (2). В POI видны три перегрузки (жизнеспособные), которые видны:

  1. шаблон функции
  2. е (интермедиат)
  3. е (двойной).

Однако вызов перенаправляется на 'f (int)', так как это лучшее совпадение.

Таким же образом, POI для 'f2 (2)' является закрывающей скобкой main. Аргумент по умолчанию 'f1' снова ищется из этого POI и преобразуется в 'f1 (int)', что является наилучшим соответствием из всех трех доступных перегрузок.

Спасибо, @litb. Пересмотрено после того, как @litb исправил мое понимание:

double f1(double d){cout << 1; return 0.0;} 

template<class T> void f2(T t1, T t2 = f1(T())){} 

template<class T> void g(T t){ 
        f1(t);            // this is the interesting call. 
} 

struct A{
        friend A f1(A const &){cout << 2; return A();} 
};

int main(){ 
        g(A());   // 'f1(t)' resolves to friend function declaration
        f2(A());  // The call to 'f1' in default argument also resolves to friend 
                  // function declaration
                  // This is because for non dependent names, only ADL is performed
                  // at POI which is at closing brace of main.
}     // POI for f1(t), Also POI for f2(2) in that order

Помните, что в обоих вышеупомянутых вызовах есть две перегрузки, которые являются кандидатами. Функция namspace 'f1 (double)' и объявление функции-друга 'f1' (найдено из-за ADL). Поскольку это единственная жизнеспособная функция, вызовы преобразуются в объявление друга 'f1'.

Я думаю, что пункт 3 означает это:

template<class A> struct T{
        T(int x = 0){}
};

template<class A> struct U{
        U():t(f(A())){}

        T<A> t;
}; // POI of 'gt' instantiation

T<int> gt(f(2));         // At this point 'f' is not found, hence error

int f(int x){return x;}

int main(){
        U<int> u;
} // There are 2 POIs here 'U<int>::T<int>' and 'U<int>' and in that order
  // Therefore 'f' is visible from here.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...