在 VC++2008 Express 中查找不依赖于模板参数的名称。它是一个错误吗?

Posted

技术标签:

【中文标题】在 VC++2008 Express 中查找不依赖于模板参数的名称。它是一个错误吗?【英文标题】:Name lookup for names not dependent on template parameter in VC++2008 Express. Is it a bug? 【发布时间】:2010-05-05 16:24:59 【问题描述】:

在尝试使用 C++ 模板时,我设法生成了这个简单的代码,其输出不同于我对 C++ 规则的理解所期望的。

void bar(double d)

    std::cout << "bar(double) function called" << std::endl;


template <typename T> void foo(T t)

    bar(3);


void bar(int i)

    std::cout << "bar(int) function called" << std::endl;


int main()

    foo(3);
    return 0;

当我在 VC++2008 Express 中编译这段代码时,函数 bar(int) 被调用。这将是行为,我希望模板正文中的bar(3); 依赖于模板参数。但事实并非如此。我发现here 的规则说“C++ 标准规定,在解析模板函数或类时,所有不依赖于模板参数的名称都绑定到它们当前的定义”。我错了吗,解析模板函数foobar的“当前定义”是 void bar(double d);?如果我错了,为什么不是这样。此编译单元中没有bar 的前向声明。

【问题讨论】:

如果你是对的,我不会感到惊讶。在我看来,VC++ 的模板实现完全忽略了依赖/非依赖问题。 VC++ 从不遵守标准的 2-passes 评估(第一次在读取模板定义时,第二次在模板实例化时)。它在某些地方节省了 typenametemplate 的写法,但是……不合规。 为了精确起见,您指的是标准的第 14.6.3 节非依赖名称 [temp.nondep]。 (最终草案) 【参考方案1】:

这确实是编译器中的一个错误。已知该问题存在于 VS2005 和之前的版本中(我使用 Blogspot 博客作为此类案例的笔记本,请参阅 1.3 here)。显然它也存在于 VS2008 中。

你可以用下面的简单代码测试一下

int bar(double d)  return 0; 

template <typename T> void foo(T t) 
  int i = bar(3);


void bar(int i);

int main() 
  foo(3);

这段代码格式正确(您可以使用 Comeau Online 编译器对其进行编译),但我敢打赌 VS 会卡住它,因为在这种情况下 VS 错误地实现了两阶段查找。

【讨论】:

是的,VS(至少是我的 Express 版本,但我认为它与其他编译器相同)声称代码中有错误。谢谢。【参考方案2】:

AndreyT 是正确的。事实上,您的代码实际上与标准(§14.6.3/1)中的示例相同:

void g(double);
void h();

template<class T> class Z 
public:
    void f() 
        g(1);    //calls g(double)
        h++;     //ill-formed: cannot increment function;
                 // this could be diagnosed either here or
                 // at the point of instantiation
    
;

void g(int);     // not in scope at the point of the template
                 // definition, not considered for the call g(1)

【讨论】:

以上是关于在 VC++2008 Express 中查找不依赖于模板参数的名称。它是一个错误吗?的主要内容,如果未能解决你的问题,请参考以下文章

使用 VC++ 2008 Express 进行 ATL 开发

VC 2008 Express下安装OpenCV2.3.1

无法安装 SQL Server 2008 R2 Express

Visual C++ 2008 Express 中的代码定义窗口是啥?

Visual C++ 2008 Express,将离散的 GUI 元素封装到单独的文件中

在 MS VC 2013 Express 中将 C++ dll 从 32 位转换为 64 位