我正在查看Boost中的“功能”类文档,并偶然发现了这一点:
boost::function<float (int x, int y)> f;
我必须承认这种语法对我来说非常困惑。这怎么可能是合法的C ++?
引擎盖下有什么伎俩吗?这种语法记录在何处?
答案 0 :(得分:9)
[编辑]这是对作者未经编辑的原始问题的回答,实际上是两个问题。
我必须承认这种语法非常重要 对我来说很困惑。怎么会这样 合法的C ++? :)有什么诀窍 在引擎盖下?这是语法 记录在哪里?
这是完全合法的,实际上并不太复杂。
template <class T>
class C
{
public:
T* function_pointer;
};
void fn(int x)
{
cout << x << endl;
}
int main(int argc, char** argv)
{
C<void (int x)> c;
c.function_pointer = &fn;
c.function_pointer(123); // outputs x
}
这与做的基本相同:
typedef void Function(int);
C<Function> c;
这种类型不仅适用于C ++,它也适用于C(实际类型C参数化)。这里的模板魔法在这里采用类似函数typedef的东西,并且能够检测返回值和参数的类型。解释这里的篇幅太长了,boost :: function在boost中使用了很多函数traits元模板来检索那些信息。如果你真的想花时间学习这个,你应该尝试从Boost.Type Traits中的boost :: function_traits开始理解boost实现。
但是,我想解决您的一般问题。我认为你正在努力简化几行完全可以接受的代码。通过参数化的子类构造函数传递命令子类的参数没有任何问题。是否真的值得尝试在这里涉及类型列表和boost :: function-like解决方案,从而显着增加编译时间和代码复杂性,仅此而已?
如果你想进一步减少它,只需编写一个执行任何命令子类的执行函数并将其添加到撤消堆栈中,依此类推:
typedef boost::shared_ptr<Command> CommandPtr;
void execute(const CommandPtr& cmd)
{
cmd->execute();
// add command to undo stack or whatever else you want to do
}
// The client can simply write something like this:
execute(CommandPtr(new CmdAdd(some_value) );
我真的认为试图让它变得更复杂的权衡是不值得的。 boost作者希望为boost :: function编写一个非常通用的解决方案,许多人将在许多平台和编译器中使用它。但是,他们没有尝试概括一个能够在统一的撤销系统中执行具有不同签名的功能的命令系统(从而要求即使在最初完成调用它们之后也能保留这些命令的状态并且能够撤消和重新执行 - 在不执行后续执行时重新指定原始状态数据的情况下执行它们。为此,基于继承的方法很可能是最好和最直接的方法。