用C++编写的"Pimp my Library"

Sil*_*olo 5 c++ polymorphism scala

在Scala中,有一种通常被称为"pimp my library"的设计模式.基本的想法是我们有一些类Foo(可能在某些库中我们无法修改),并且我们想要表现Foo得像它有一些方法或行为frobnicate,我们可以使用隐式类在事后添加方法.

implicit class Bar(val foo: Foo) extends AnyVal {
  def frobnicate(): Unit = {
    // Something really cool happens here ...
  }
}
Run Code Online (Sandbox Code Playgroud)

然后,如果我们有一个实例Foo,我们可以调用frobnicate它,只要Bar在范围内,Scala编译器就足够聪明,可以隐式转换FooBar.

val foo = new Foo()
foo.frobnicate() // Correctly calls new Bar(foo).frobnicate()
Run Code Online (Sandbox Code Playgroud)

我想在C++中做同样的事情.我知道C++有隐式转换,但在访问成员时它们似乎没有触发.举个具体的例子,C++中的以下代码会产生错误.

class Foo {}; // Assume we can't modify this class Foo

class Bar {
private:
  Foo foo;
public:
  Bar(Foo foo) : foo(foo) {}
  void frobnicate() {
    cout << "Frobnicating :)" << endl;
  }
};

void frobnicate(Bar bar) {
  cout << "Frobnicating :)" << endl;
}

int main() {
  Foo value;
  frobnicate(value);  // This works
  value.frobnicate(); // But this doesn't
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

value.frobnicate()线条,C++似乎并不寻求在这方面的隐式转换.

main.cc:30:9:错误:'class Foo'没有名为'frobnicate'的成员

注意:我现在正在使用C++ 11进行编译.粗略地看一下较新的C++版本,从那时起,似乎没有什么会影响这个问题.C++ 11兼容的解决方案是理想的,但是出于教学目的,在新的C++版本中实现这一点的方法也会很好.

Fra*_*ank 9

你所描述被称为ü nified ˚F油膏Ç所有小号 yntax(UFCS),不能用C++做今天的.任何使用D中的范围和算法链接的人都可以证明这将是多么令人惊奇.

缺乏UFCS支持实际上是为什么一般的现代智慧是使用自由浮动函数和ADL用于不需要虚拟或封装的任何东西的主要原因之一.

有提议将D的UFCS引入该语言,但它仍然只是一个提议:

https://isocpp.org/files/papers/N4165.pdf

编辑:对于想知道为什么我们想要这个功能的人,想象能够编写以下内容:

std::vector<int> foo(const std::vector<int>& v) {
  return v.filter([](int x) {return x > 5;})
          .map([](int x) {return x*x;})
          .sort();
}
Run Code Online (Sandbox Code Playgroud)