Name resolution and Point of instantiation in Temp

2019-09-01 02:09发布

This is the statement from ISO C++ Standard 14.6.4.1 Point of instantiation

 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.

I am unable to write a programs for this whole section. I am trying to write a programs for this section from yesterday.

Please, normally I would try to ask a 1 or more points. In any section. But here I am unable to understand a single point in this section.

So, kindly can any one provide me a code for this sections to understand.

标签: c++ templates
2条回答
Emotional °昔
2楼-- · 2019-09-01 02:31

The first two statements explain where the instantiation point of certain template constructs are; it doesn't introduce new template constructs. So you can reuse your previous examples.

The third statement (14.6.4.1/6) tells us what the point of instantiation points is: they are the point where names are looked up during the second phase of name lookup. Names that are declared before the instantiation point are visible; those declared afterwards are not. (In the first phase of two-phase name lookup, non-dependent names are looked up in the set of declarations that precede the template definition).

So, given:

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

the instantiation contexts of the expression T()+T() is the set of declarations that precede the respective instantiation points of foo<T>. The name operator+ is looked up in those contexts, and includes declarations that follow this definition but precede the instantiation point.

查看更多
等我变得足够好
3楼-- · 2019-09-01 02:43

There seems always tons of questions with regards to instantiation context.

The example given by MSalters is problematic:

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

consider the following code:

#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>();
}

That compiles and runs on all compilers, but if you put the class A definition into a namespace:

#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 will fail to compile, but VC++ and gcc compiles. Why? which compiler conforms to the spec?

Frankly, I don't know. Some compiler, like gcc even contradicts itself in this area. Consider the following code:

#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>();
}

Simply change from "operator+" to a function named "g", gcc fails to compile???Why???

If the Spec is correct, then why GCC cannot find 'g'?

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.

When I was reading Bjarne Stroustrup's "The C++ Programming Language, 4th Edition", 26.3.5 Template and Namespaces, he has this example:

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

Here, f(t) is clearly dependent, so we cannot bind f at the point of definition. To generate a specialization for g(N::A), the compiler looks in namespace N for functions called f() and fins N::f(N::A).

The f(int) is found because it is in scope at the point of definition of the template. The f(double) is not found because it is not in scope at the point of definition of the template, and argument-dependent lookup does not find a global function takes only arguments of built-in types.

So it's a mess!

查看更多
登录 后发表回答