【问题标题】:C++, overloading std::swap, compiler error, VS 2010C++,重载 std::swap,编译器错误,VS 2010
【发布时间】:2011-01-02 21:13:14
【问题描述】:

我想在我的模板类中重载 std::swap。在以下代码中(简化)

#ifndef Point2D_H
#define Point2D_H

template <class T>
class Point2D
{
    protected:

            T x;
            T y;

    public:
            Point2D () :  x ( 0 ),  y ( 0 ) {}
            Point2D( const T &x_, const T &y_ ) :  x ( x_ ), y ( y_ ) {}
            ....

    public:

            void swap ( Point2D <T> &p );   
};


template <class T>
inline void swap ( Point2D <T> &p1, Point2D <T> &p2 ) { p1.swap ( p2 ); }


namespace std
{
    template <class T>
    inline void swap ( Point2D <T> &p1, Point2D <T> &p2 ) { p1.swap ( p2 ); }
}

template <class T>
void Point2D <T>::swap ( Point2D <T> &p ) 
{
    using (std::swap);
    swap ( x, p.x );
    swap ( y, p.y );
}

#endif

存在编译器错误(仅在 VS 2010 中):

error C2668: 'std::swap' : ambiguous call to overloaded 

我不知道为什么,std::swap 应该被过度加载...使用 g ++ 代码可以完美地工作。如果没有模板(即 Point2D 不是模板类),此代码也可以工作..

感谢您的帮助。

【问题讨论】:

  • 你不应该重载 std::swap,你应该专门化它。对 villintehaspam 所链接问题的回答解释了这种区别并举例说明。但是部分特化对于函数模板是不可能的,所以你必须在你自己的命名空间中定义你的实现并依赖 Koenig 查找。
  • 注意:标准规定“显式特化声明不应是友元声明”。不过这是个好主意。

标签: c++ visual-studio-2010 overloading swap


【解决方案1】:

请参阅How to overload std::swap() 。基本上,您可以对 std::swap 进行专门化,但不能进行重载。

因此,可以为特定的 Point&lt;&gt; 类型(例如 Point&lt;float&gt;)创建特定版本,但不能为任何 Point&lt;T&gt; 创建特定版本。

【讨论】:

  • 不,但是...您可以在定义 Point&lt;T&gt; 的命名空间中放置一个重载的交换,它将通过 Koenig 查找(也称为参数相关查找)找到。
  • @Ben Voigt:对于像在自己的代码中调用 swap(a,b) 这样的简单情况是正确的 - 但是有很多代码明确调用 std::swap (我认为这是至少在标准库的某些实现中是这样),那将无济于事。
  • @villintehaspam 为更多数据类型(double、floast、...)专门交换有点不舒服:inline void swap (Point2D &p1, Point2D &p2) { p1.swap ( p2 ); }
  • @Ian,是的。通常,需要专门化 std::swap 是因为您可以对幼稚复制进行性能改进。对于像 double、int 等简单的情况。我认为你不需要在你的例子中为像 Point2D 这样的类专门化它。所以不要这样做 - 确保添加一个复制构造函数和赋值运算符。
  • @villintehaspam 你是对的,谢谢你的评论。我想加快点的排序,所以我需要在存储 2D 点的容器中专门为 Point2D 的 std::swap...
【解决方案2】:

我知道您没有问过这个问题,但是由于您使用的是 VC10,因此提供了 move 构造函数 和 move 赋值运算符 应该使 std::swap() 为您的类型提供最佳性能。

【讨论】:

    【解决方案3】:

    之所以模棱两可,是因为你提供了 ::swap 和 std::swap,然后你 using'd std::swap。现在您在全局命名空间中同时拥有 ::swap 和 std::swap 。所以编译器不知道你是指 ::swap 还是 std::swap。

    但是,提供移动操作符/构造函数将使交换以最佳的方式执行。

    【讨论】:

      猜你喜欢
      • 2014-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多