使用限定类型实例化的模板内函数的名称解析 [英] Name resolution of functions inside templates instantiated with qualified types

查看:42
本文介绍了使用限定类型实例化的模板内函数的名称解析的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下 C++ 代码示例:

Consider the following C++ code example:

namespace n
{
    struct A {};
}

struct B {};

void foo(int) {}

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

void foo(n::A) {}
void foo(B) {}


int main()
{
    quux<n::A>(); // Error (but works if you comment out the foo(int) declaration)
    quux<B>();    // Works

    return 0;
}

如注释中所示,模板实例化 quux() 导致编译器错误(在 GCC 4.6.3 上):

As indicated in the comment, the template instantiation quux<n::A>() causes a compiler error (on GCC 4.6.3):

foo.cpp: In function ‘void quux() [with T = n::A]’:
foo.cpp:22:16:   instantiated from here
foo.cpp:13:5: error: cannot convert ‘n::A’ to ‘int’ for argument ‘1’ to ‘void foo(int)’

谁能给我解释一下这是怎么回事?我本来希望它与 quux() 一样工作.当 foo 被认为是依赖时,它必须与某些有关.不幸的是,我的 C++ foo 不够好.当 foo(int) 声明不存在时,这个例子编译得很好,这也让我感到惊讶.

Can someone explain to me what is going on? I would have expected for it to work the same as with quux<B>(). It must have something to do with when foo is considered dependent. Unfortunately my C++ foo is not good enough. The example compiles fine, when the foo(int) declaration is not present, which is also surprising to me.

欢迎提供任何提示、解释和解决方法.

Any hints, explanations and workarounds are welcome.

更新 1:

我不想(读不能)在 quux 的定义之前移动 foo(n::A) 的声明(这将避免错误).

I do not want to (read cannot) move the declaration of foo(n::A) before the definition of quux (which would avoid the error).

更新 2:

感谢 David 指出相关问题 模板函数调用被模板前声明的错误签名的函数混淆了.Johannes Schaub 接受的答案 - litb 提出了一个包装类解决方案,这也适用于我的情况作为一种解决方法.但是,我对它并不是 100% 满意.

Thanks for David for pointing out the related question Template function call confused by function with wrong signature declared before template. The accepted answer by Johannes Schaub - litb proposes a wrapper class solution, that would also work in my case as a workaround. However, I'm not 100% happy with it.

更新 3:

我通过将 foo(n::A) 的定义放在命名空间 n 中解决了这个问题.感谢 Jesse Good 和 bames53 的有用回答,他们不仅指出了标准的相关部分,还提供了替代解决方案.感谢 David Rodríguez - dribeas 在我没有正确理解提议的解决方案和所有其他贡献者时的解释.

I solved the issue by putting the definition of foo(n::A) in namespace n. Thanks for the helpful answers of Jesse Good and bames53 that not only point out the relevant sections of the standard, but also provide alternative solutions. Thanks to David Rodríguez - dribeas for his explanation when I did not understand the proposed solutions properly and all other contributors.

推荐答案

我认为规则是 14.6.4.2p1:

I think the rule is 14.6.4.2p1:

对于依赖模板参数的函数调用,使用通常的查找规则 (3.4.1,3.4.2, 3.4.3) 除了:

For a function call that depends on a template parameter, the candidate functions are found using the usual lookup rules (3.4.1, 3.4.2, 3.4.3) except that:

——对于使用非限定名称查找 (3.4.1) 或限定名称查找 (3.4.3) 的查找部分,仅找到了模板定义上下文中的函数声明.

— For the part of the lookup using unqualified name lookup (3.4.1) or qualified name lookup (3.4.3), only function declarations from the template definition context are found.

——对于使用关联命名空间(3.4.2)的查找部分,仅在模板定义上下文中找到的函数声明或者找到模板实例化上下文.

— For the part of the lookup using associated namespaces (3.4.2), only function declarations found in either the template definition context or the template instantiation context are found.

void foo(n::A) {} 在模板定义上下文中不可见,因为它出现在后面而 foo 不是在与 n::A 相同的命名空间中.因此,它需要在模板定义之前可见,或者包含在相同的命名空间中,如下所示:

void foo(n::A) {} is not visible in the template definition context because it comes after and foo is not in the same namespace as n::A. So it needs to be either visible before the template definition or included in the same namespace like below:

namespace n
{
    void foo(n::A) {}
}

这篇关于使用限定类型实例化的模板内函数的名称解析的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆