未考虑与参数相关的查找
argument dependent lookup not considered
为什么依赖于参数的查找不考虑Foo::dynamicCast
,难道不应该考虑命名空间Foo吗?因为基类在这个命名空间中?
#include <memory>
using namespace std;
namespace Foo
{
template<typename P, typename T> P*
dynamicCast(T* t)
{
return dynamic_cast<P*>(t);
}
class Base
{
public:
virtual ~Base() = default;
};
}
namespace Test
{
class Derived : public Foo::Base
{
};
}
shared_ptr<Foo::Base> b = make_shared<Test::Derived>();
auto d = dynamicCast<Test::Derived>(b.get());
为了理解您有一个带有模板的函数调用,而不是一堆<
和>
运算符,编译器必须知道您有一块函数模板;为了理解这一点,它必须知道在哪个命名空间中查找它。为了知道这一点。它必须理解函数参数的命名空间。为了理解,它必须知道周围有函数自变量。正如我们所看到的,这取决于知道一开始就有一个函数调用。编译器直到找到模板声明才知道。看到问题了吗?
因此,只有当函数调用中的后缀表达式是不合格id时,才会考虑ADL。哪个dynamicCast<Test::Derived>
是而不是<edit>仅当已知dynamicCast
是模板名称时,该名称是在正常的非限定查找过程中确定的,不查找声明模板的命名空间。
正如@T.C.所观察到的,可以在全局命名空间中声明一个名为dynamicCast
的无关函数模板,以使ADL工作。
<编辑>
在一个更好的世界里,我们可以选择在任何上下文中编写template foo<whatever>
,并消除尖括号的歧义。也许在C++20中。
另一个例子是CCD_ 8。如果没有using语句,就无法get<3>(some_tuple)
。
您可以通过将作为模板参数传递的参数作为标记类型来解决此问题。你也可以做一个两步的外部函数加上内部ADL标记调度查找(所以公共函数必须是合格的,但可以完成基于内部标记的ADL的定制点)。
// tag utilities:
template<class T>struct tag_t{using type=T;constexpr tag_t(){};};
template<class T>constexpr tag_t<T> tag={};
namespace some{
template<class T, class U>
T* dynamic(tag_t<T>, U* u){
return dynamic_cast<T>(u);
}
struct bob{};
}
现在dynamic(tag<int>,new some::bob{})
将通过ADL找到dynamic
。
我没有章节和诗句的标准为你。
相关文章:
- 参数相关查找和流运算符重载
- 编译器在C++中调用另一个函数时,在参数中查找已删除的构造函数
- 当数组在C++中用作参数时,查找数组的元素数
- C++ 普通查找与参数相关查找
- 运算符<<依赖于参数的查找不在全局命名空间中查找
- 查找可变参数列表的字符串格式指定符
- 在参数相关查找之前进行模板替换的任何方法(或解决方法?
- 如何查找/删除具有特定参数的结构向量的元素
- C 中的参数查找
- 支持与参数有关的查找的编译器
- 为什么在其他函数中声明的函数不参与参数相关查找?
- 使用查找表选择具有运行时索引的可变参数类型
- 为什么在这种情况下不考虑依赖于参数的查找?
- 数组作为函数参数查找数组长度时出错
- 仅通过参数查找重载地址
- 重载函数查找轮廓的实例与参数列表不匹配
- 我如何避免使用依赖于参数的查找明确专门化模板化功能
- 查找参数包的唯一值的数目
- 查找参数时出错
- 用于查找参数是否为类的不同模板语法