C++ weird syntax spotted in Boost template parameters

对着背影说爱祢 提交于 2019-12-03 07:00:14

[Edit] This is an answer to the author's original, unedited question which was actually two questions.

I must admit this syntax is highly confusing for me. How can this be legal C++ ? :) Is there any trick under the hood ? Is this syntax documented anywhere ?

This is perfectly legal and it's actually not too complicated.

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
}

It's basically the same thing as doing:

typedef void Function(int);
C<Function> c;

This type is not just applicable C++, it's just as applicable in C (the actual type C is parameterized to). The template magic here is taking something like the Function typedef here and being able to detect the types of the return values and arguments. Explaining that would be too lengthy here and boost::function uses a lot of the function traits meta-templates in boost to retrieve that information. If you really want to spend the time to learn this, you should try to understand the boost implementation starting with boost::function_traits in Boost.Type Traits.

However, I want to address your general problem. I think you are trying too hard to simplify a couple of lines of perfectly acceptable code. There's nothing wrong with passing the arguments for your command subclasses through their parameterized subclass constructors. Is is really worth trying to involve typelists and boost::function-like solutions here, thereby increasing compile times and code complexity significantly, just for that?

If you want to reduce it further, just write an execute function that will execute any command subclass and add it to the undo stack and so on:

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) );

I really think the trade-off of trying to make it any more complicated isn't worth it. The boost authors wanted to write an extremely general-purpose solution for boost::function which would be used by many people across many platforms and compilers. However, they didn't try to generalize a command system capable of executing functions with different signatures across a unified undo system (thereby requiring the state of these commands to be preserved even after one is initially finished calling them and be able to undo and re-execute them without re-specifying the original state data on subsequent executions). For that, your inheritance-based approach is most likely the best and most straightforward one.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!