使用指令vs使用C ++中的声明交换 [英] using directive vs using declaration swap in C++

查看:151
本文介绍了使用指令vs使用C ++中的声明交换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请参阅以下代码:

  #include< algorithm> 

命名空间N
{

模板< typename T>
class C
{
public:
void SwapWith(C& c)
{
using namespace std; //(1)
// using std :: swap; //(2)
swap(a,c.a);
}
private:
int a;
};

template< typename T>
void swap(C< T& c1,C< T& c2)
{
c1.SwapWith(c2);
}

}

namespace std
{

template< typename T> void swap(N :: C T& c1,N :: C T& c2)
{
c1.SwapWith(c2);
}

}

如上所述,在Visual Studio 2008/2010上编译。错误是:

 'void N :: swap(N :: C& T>&)':不能推导出'N :: C< T> &'from'int'。但是,如果我注释掉(1)和取消注释(2),它将编译为OK。 使用命名空间std 使用std :: swap 之间的区别是什么,这解释了这种行为?

解决方案

第一种情况是一个using指令( using namespace X ),在 X 的第一个公共命名空间中,来自命名空间 X 的名称将可用于常规查找,范围。在这种情况下, :: N :: std 的第一个公共命名空间祖先是 :: ,所以using指令将使 std :: swap 仅当lookup命中 ::



这里的问题是,当查找开始时,它将查看函数内部,然后在类中,然后在 N ,它会找到 :: N :: swap 。由于检测到潜在的过载,正常查找不会继续到外部名称空间 :: 。因为 :: N :: swap 是一个函数,编译器将执行ADL(Argument dependent lookup),但是基本类型的相关命名空间集是空的,带来任何其他过载。此时查找完成,并开始重载分辨率。它将尝试匹配当前(单个)重载与调用,它将无法找到从 int 转换为参数 ::



另一方面,使用声明( using std :: swap )提供实体在当前上下文中的声明(在这种情况下在函数本身内部)。 Lookup会立即找到 std :: swap ,并使用 :: std :: swap 停止常规查找,并使用它。


Please refer to the code below:

#include <algorithm>

namespace N
{

    template <typename T>
    class C
    {
    public:
        void SwapWith(C & c)
        {
            using namespace std; // (1)
            //using std::swap;   // (2)
            swap(a, c.a);
        }
    private:
        int a;
    };

    template <typename T>
    void swap(C<T> & c1, C<T> & c2)
    {
        c1.SwapWith(c2);
    }

}

namespace std
{

    template<typename T> void swap(N::C<T> & c1, N::C<T> & c2)
    {
        c1.SwapWith(c2);
    }

}

As written above, the code doesn't compile on Visual Studio 2008/2010. The error is:

'void N::swap(N::C<T> &,N::C<T> &)' : could not deduce template argument for 'N::C<T> &' from 'int'.

However, if I comment out (1) and uncomment (2), it will compile OK. What is the difference between using namespace std and using std::swap that explains this behavior?

解决方案

The first case is a using directive (using namespace X), and what it means is that the names from namespace X will be available for regular lookup, in the first common namespace of X and the current scope. In this case, the first common namespace ancestor of ::N and ::std is ::, so the using directive will make std::swap available only if lookup hits ::.

The problem here is that when lookup starts it will look inside the function, then inside the class, then inside N and it will find ::N::swap there. Since a potential overload is detected, regular lookup does not continue to the outer namespace ::. Because ::N::swap is a function the compiler will do ADL (Argument dependent lookup), but the set of associated namespaces for fundamental types is empty, so that won't bring any other overload. At this point lookup completes, and overload resolution starts. It will try to match the current (single) overload with the call and it will fail to find a way of converting from int to the argument ::N::C and you get the error.

On the other hand a using declaration (using std::swap) provides the declaration of the entity in the current context (in this case inside the function itself). Lookup will find std::swap immediately and stop regular lookup with ::std::swap and will use it.

这篇关于使用指令vs使用C ++中的声明交换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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