我经常对这样的类成员函数的顺序调用感到恼火(忽略新用法,它是针对 Qt 的,但它与 Qt 并不严格相关)
A a = new A();
a->fun1("one");
a->fun2(1, 2);
...
a->fun10("end");
我总觉得这样的代码应该写成简单的指令,而不是项目主线。
来自 Qt 的简单示例:
auto* spinBox = new QSpinBox();
spinBox->setRange(-100, 100);
spinBox->setValue(50);
spinBox->setSingleStep(5);
newLayout->addWidget(spinBox);
但我更愿意用简单的单行来完成此操作而不是那样。所以我写了这样的东西:
class {
public:
template<class X>
auto& operator()(X* ptr) {
this->ptr = ptr;
return *this;
}
template<class X, class R, class... Args>
auto& operator()(R (X::* fun)(Args...), Args... args) {
if(ptr == nullptr) {
std::cerr << "Editor can't edit nullptr" << std::endl;
return *this;
}
auto call = std::mem_fn(fun);
call(*static_cast<X*>(ptr), args...);
return *this;
}
template <class X>
operator X*() {
auto* result = static_cast<X*>(ptr);
ptr = nullptr;
return result;
}
private:
void *ptr = nullptr;
} EDITOR;
现在的用法:
newLayout->addWidget(EDITOR(new QSpinBox)(&QSpinBox::setRange,-100, 100)(&QSpinBox::setValue, 50)(&QSpinBox::setSingleStep, 5));
除了类型不安全之外,这是个好方法吗? (我可以忍受)
---
EDIT
---
另一种类型安全的方法是:
template<class X>
class EDITOR2 {
public:
EDITOR2(X* ptr) {
this->ptr = ptr;
}
template<class R, class... Args>
auto& operator()(R (X::* fun)(Args...), Args&&... args) {
if(ptr == nullptr) {
std::cerr << "Editor can't edit nullptr";
return *this;
}
auto call = std::mem_fn(fun);
call(*ptr, args...);
return *this;
}
operator X*() {
return ptr;
}
X *ptr;
};
与用法:
newLayout->addWidget(EDITOR2<QSpinBox>(new QSpinBox)(&QSpinBox::setRange, -100, 100)(&QSpinBox::setValue, 50)(&QSpinBox::setSingleStep, 5));
但这需要每次重新创建编辑器对象,并添加额外的使用代码。