模板中的名称解析和实例化点

时间:2010-09-28 06:41:09

标签: c++ 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.

我无法为整个部分编写程序。我试图从昨天开始为这一部分编写程序。

请,通常我会尝试提出一个或多个积分。在任何部分。但在这里我无法理解本节中的一点。

所以,任何人都可以为我提供一些代码供这些部分理解。

2 个答案:

答案 0 :(得分:2)

前两个语句解释了某些模板结构的实例化点在哪里;它没有引入新的模板结构。因此,您可以重复使用之前的示例。

第三个语句(14.6.4.1/6)告诉我们实例化要点是什么:它们是在名称查找的第二阶段查找名称的点。在实例化点之前声明为的名称是可见的;之后宣布的不是。 (在两阶段名称查找的第一阶段,在模板定义之前的声明集中查找非依赖名称。)

所以,给定:

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

表达式T()+T()的实例化上下文是在foo<T>的相应实例化点之前的一组声明。在这些上下文中查找名称operator+,并包括遵循此定义但在实例化点之前的声明。

答案 1 :(得分:1)

关于实例化上下文似乎总是有很多问题。

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无法编译???为什么???

如果Spec正确,那么为什么GCC找不到'g'?

  

6.依赖于模板参数的表达式的实例化上下文是具有外部链接的声明集合
  在模板实例化之前声明   在同一翻译单位专业化。

当我阅读Bjarne Stroustrup的“The C ++ Programming Language,4th Edition”,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()和fins N :: f(N :: A)的函数。

找到f(int)是因为它在模板定义的范围内。找不到f(double),因为它不在模板定义的范围内,并且参数依赖查找没有找到全局函数只接受内置类型的参数。

所以这太乱了!