与参数有关的名称查找和typedef [英] Argument dependent name lookup and typedef

查看:88
本文介绍了与参数有关的名称查找和typedef的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不希望此代码可以编译,但是可以。我的理解是 func(d)会在全局名称空间中查找名为 func的函数,但还会在任何传入的参数的名称空间中(依赖于参数的查找)

I would not have expected this code to compile, but it does. My understanding is that func(d) it looks in the global namespace for a function called "func" but also in the namespace of any passed in parameters (Argument dependent lookup)

但是在这种情况下,该参数位于全局名称空间中。那么为什么在ns名称空间中找到 func呢?是否有特殊的规则说如果参数类型是typedef,那么它使用基础类型的名称空间而不是实际参数的名称空间?

But in this case the parameter is in the global namespace. So why does it find "func" in the ns namespace? Are there special rules saying that if the parameter type is a typedef then it uses the namespace of the underlying type rather than the namespace of the actual parameter?

这似乎是是,但是我找不到任何支持此方法的东西。

This appears to be true but I can't find anything supporting this... Is it the expected behavour?

namespace ns
{
    struct data {};
    void func(ns::data item) {}
};

// Create an alias "datatype" in the global namespace for ns::data
typedef ns::data datatype;


int main()
{
    datatype d;
    func(d);
}


推荐答案

其他答案已经提供了原因,如果不是这样:

The other answers already provide the reason, if not the rationale:


A typedef 是类型的别名,它将由编译器解析为实际类型。

A typedef is an alias to a type, and it will be resolved by the compiler to the actual type. Argument dependent lookup is done based on the underlying type, not the typedef.

此设计决策的理由实际上是ADL的原因用的语言。 ADL已添加到语言中,以支持操作员重载。在任何其他用例中,用户可以显式声明函数的名称空间,但是在运算符重载的情况下,这将导致卷积的代码具有反直观性:

The rationale for this design decision is actually the reason why ADL is in the language. ADL was added to the language to support operator overloading. In any other use case, the user can explicitly state the namespace of the functions, but in the case of operator overloading that would lead to convoluted code that is counter intuitive:

std::string s("Hi");
std::cout.operator<<(s); // or is it std::operator<<(std::cout,s)??

因此,该语言添加了查找规则,以查找不同名称空间中的运算符(和函数),特别是在函数参数的名称空间中。在这种情况下,在 std :: 内部,以防 operator<< 需要一个 std :: string 不是 std :: cout 的成员。相同的行为扩展到相同名称空间中的所有自由函数(为什么不这样做),从而允许类型的接口不仅包含成员函数,而且还包含相同名称空间中的自由函数。

So the language added rules for lookup to find operators (and functions) in different namespaces, and in particular in the namespace of the arguments to the function. In this case inside std:: in case the operator<< that takes a std::string is not a member of std::cout. The same behavior is extended to all free functions in the same namespace (why not?) allowing the interface of a type to include not only member functions but also free functions in the same namespace.

现在,如果您专注于此,目的是访问属于该类型接口的功能,并且这些功能是通过 定义的。当您在其他命名空间中添加typedef时,您只是在创建一个引用原始类型的简写形式。类型提供的所有功能(例如 operator<<(std :: ostream&,MyType))都在原始名称空间中,而在名称空间中则没有 typedef 的值。您想要 ADL查看定义实型而不是创建别名的名称空间。

Now if you focus on this, the purpose is accessing functions that are part of the interface of the type, and those are defined with the type. When you add a typedef in a different namespace you are just creating a shorthand to refer to the original type. All of the functions that were provided with the type (for example operator<<(std::ostream&,MyType)) are in the original namespace, no in the namespace of the typedef. You want ADL to look into the namespace where the real type was defined, not where the alias was created.

这篇关于与参数有关的名称查找和typedef的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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