在Scala中,有一种通常被称为“pimp my library”的设计模式。基本的想法是我们有一些类Foo
(可能在某些我们无法修改的库中),我们希望Foo
表现得像它有一些方法或行为frobnicate
,我们可以使用隐式类在事后添加方法。
implicit class Bar(val foo: Foo) extends AnyVal {
def frobnicate(): Unit = {
// Something really cool happens here ...
}
}
然后,如果我们有一个Foo
的实例,我们就可以在其上调用frobnicate
,只要Bar
在范围内,Scala编译器就足够智能化了将Foo
投射到Bar
。
val foo = new Foo()
foo.frobnicate() // Correctly calls new Bar(foo).frobnicate()
我想在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;
}
在value.frobnicate()
行上,C ++似乎没有在该上下文中寻找隐式转换。
main.cc:30:9:错误:'class Foo'没有名为'frobnicate'的成员
注意:我正在使用C ++ 11进行编译。粗略地看一下较新的C ++版本,从那时起,似乎没有什么会影响这个问题。 C ++ 11兼容的解决方案是理想的,但是出于教学目的,在新的C ++版本中执行此操作的方法也会很好。
答案 0 :(得分:9)
您所描述的内容称为 U nified F unction C 所有 S yntax(UFCS),以及到目前为止,无法在C ++中完成。任何使用D中的范围和算法链接的人都可以证明这将是多么令人惊奇。
缺乏UFCS支持实际上是一般现代智慧使用自由浮动函数和ADL用于任何不需要虚拟或封装的主要原因之一。
有人建议将D&D的UFCS引入该语言,但它仍然只是一个提案:
https://isocpp.org/files/papers/N4165.pdf
编辑:对于想知道我们为什么会想要这个功能的人来说,想象一下能够编写以下内容:
y
答案 1 :(得分:3)
虽然您无法完全按照要求执行操作,但您可以继承Foo
并延长它。
class Bar : public Foo{
public:
void frobnicate() {
cout << "Frobnicating :)" << endl;
}
}
现在Bar
包含Foo
所有内容以及新方法。见http://www.cplusplus.com/doc/tutorial/inheritance/
答案 2 :(得分:1)
C ++似乎并没有在该上下文中寻找隐式转换。
这是正确的。您正在寻找的机制并不存在于该语言中。