0

我创建了一个函子,它定义了自己的交换函数。为简单起见,假设函子的运算符签名是 int (int)。如果我用那个仿函数初始化两个 std::function,比如 std_func1 和 std_func2,交换它们会调用仿函数的用户实现的交换函数吗?提前致谢。

这是我尝试过的:

#include <iostream>
#include <vector>
#include <boost/function.hpp>

using namespace std;

class myclass {

public:
  myclass(int n):data_(n,0){}

  void swap(myclass& rhs) {
    using std::swap;
    std::cout << "swapping myclass" << '\n';
    data_.swap(rhs.data_);
  }

private:
  vector<int> data_;
};


struct square {

  square(int n):B(n){}

  int operator()(int x) {
    return x*x;
  }

  myclass B;

  void swap(square& rhs) {
    using std::swap;
    std::cout << "swapping square" << '\n';
    B.swap(rhs.B);
  }
};

void swap(myclass& a, myclass& b) {
  a.swap(b);
}

void swap(square& a, square& b) {
  a.swap(b);
}



using myfunction = std::function<int (int)>;

int main () {
  myfunction myf1(square(10));
  myfunction myf2(square(20));
  myf1.swap(myf2);      /* does not use user-implemented swap functions */

  return 0;
}
4

2 回答 2

2

文档_std::swap

大数据类型可以提供此函数的重载版本,以优化其性能。值得注意的是,所有标准容器都以这样一种方式对其进行了专门化,即只交换少数内部指针而不是它们的全部内容,从而使它们在恒定时间内运行。

标准库的许多组件(在 std 中)以非限定方式调用 swap 以允许调用非基本类型的自定义重载而不是此通用版本:在与它们所针对的类型相同的命名空间中声明的 swap 的自定义重载提供通过在此通用版本上的依赖于参数的查找来选择。

免费功能的文档std::swap(std::function)说:

有效地调用 lhs.swap(rhs)。

而成员函数的文档std::function::swap没有指定任何类型的东西。

因此,基本上,答案是“对此无法保证”,即使从第一个引用来看,大多数实现确实通过使用不合格的调用来调用用户定义的swap.

于 2013-07-31T09:01:05.603 回答
0

std::function::swap(function& other) noexcept定义为:

效果:互换目标*thisother

虽然不清楚它是否允许实现调用swap目标,但很自然地假设它不允许,因为swap一旦将目标放入std::function. swap这意味着实现在用户定义存在的情况下了解和调用用户定义需要付出巨大的努力(并且运行时效率低下) (同时在用户定义swap不可用时维护备份实现)。

此外,在可用时使用用户定义的交换,但在所有其他情况下只交换指针,将是相当不一致和混乱的。

在您的特定情况下,此函数标记为noexcept,而您的square::swap实现未标记,因此任何实现调用它都是不合法的(因为它可能会违反noexcept合同)。

于 2013-07-31T09:27:07.663 回答