使用从字符串中提取的参数调用函数
我正在考虑以下问题:
我得到格式如下的字符串:
functionname_parameter1_parameter2_parameter3
otherfunctionname_parameter1_parameter2
.
.
.
并且我想使用给定的参数调用该函数。 假设我有一个函数测试:
void test(int x, float y, std::string z) {}
并且我收到一条消息:
test_5_2.0_abc
然后我希望函数测试能够像这样自动调用:
test(5, 2.0, "abc");
您对如何在 C++ 中完成此操作有任何提示吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
更新:更新了
stream_function
以修复@Nawaz在评论中提到的参数求值顺序问题,并且还删除了std::function
提高效率。请注意,评估顺序修复仅适用于 Clang,因为 GCC 不遵循此处的标准。可以在 此处。这通常不是那么容易实现的。我围绕
std::function
编写了一个小包装类,从std::istream
中提取参数。下面是一个使用 C++11 的示例:在 Clang 3.3 下编译并按预期工作(小型实例< /a>)。
再次组合这堂课很有趣,希望你喜欢。请注意,您需要稍微修改代码才能适用于您的示例,因为 C++ IOstream 使用空格作为分隔符,因此您需要将消息中的所有下划线替换为空格。不过应该很容易做到,之后只需从您的消息构造一个
std::istringstream
即可:Update: Updated
stream_function
to fix the argument-evaluation-order problem @Nawaz mentioned in the comments, and also removed thestd::function
for improved efficiency.Note that the evaluation-order fix only works for Clang, as GCC doesn't follow the standard here.An example for GCC, with manual order-enforcement, can be found here.This is generally not that easy to accomplish. I wrote a little wrapper class around
std::function
once that extracts the arguments from astd::istream
. Here's an example using C++11:Compiles under Clang 3.3 and works as expected (small live example).
It was fun to hack that class together again, hope you enjoy. Note that you need to modify the code a little to work for your example, since C++ IOstreams have whitespace as delimiter, so you'd need to replace all underscores in your message with spaces. Should be easy to do though, after that just construct a
std::istringstream
from your message:你几乎不能,C++ 对函数没有任何类型的反射。
接下来的问题是你能接近多远。如果适合的话,这样的接口是相当合理的:
其中
registered_functions
是map>
,并且您有显式地执行以下操作:对于可以以这种方式调用的每个函数。
make_registration 将是一个相当复杂的模板函数,它将函数指针作为参数并返回一个 std::function 对象,该对象在调用时将字符串分割成块,并检查那里有正确的数字,使用boost::lexical_cast将每个数字转换为正确的参数类型,最后调用指定的函数。它会知道
make_registration
的模板参数中的“正确类型”——要接受任意多个参数,这必须是 C++11 可变参数模板,但您可以通过以下方式伪造它:重载和可选参数会增加进一步的复杂性。
虽然我对它们一无所知,但我希望有针对 SOAP 或其他 RPC 协议的 C++ 支持框架,其中可能包含一些相关代码。
You pretty much can't, C++ doesn't have any kind of reflection on functions.
The question then is how close you can get. An interface like this is pretty plausible, if it would suit:
Where
registered_functions
is amap<string,std::function<void,string>>
, and you have to explicitly do something like:for each function that can be called in this way.
make_registration
would then be a fairly hairy template function that takes a function pointer as a parameter and returns astd::function
object that when called splits the string into chunks, checks that there are the right number there, converts each one to the correct parameter type with aboost::lexical_cast
, and finally calls the specified function. It would know the "correct type" from the template argument tomake_registration
-- to accept arbitrarily many parameters this would have to be a C++11 variadic template, but you can fake it with:Dealing with overloads and optional parameters would add further complication.
Although I don't know anything about them, I expect that there are C++ support frameworks out there for SOAP or other RPC protocols, that might contain some relevant code.
你正在寻找的是反思。而这在 C++ 中是不可能的。 C++ 的设计考虑了速度。如果您需要检查库或代码,然后识别其中的类型并调用与这些类型(通常是类)关联的方法,那么恐怕这在 C++ 中是不可能的。
如需进一步参考,您可以参考此线程。
如何向 C++ 应用程序添加反射?
http://en.wikibooks.org/wiki/C%2B%2B_Programming/RTTI
为什么C++没有反射?
What you are looking for is reflection. And it is not possible in C++. C++ is designed with speed in mind. If you require inspection of a library or code and then identify the types in it and invoke methods associated with those types (usually classes) then I am afraid it is not possible in C++.
For further reference you can refer to this thread.
How can I add reflection to a C++ application?
http://en.wikibooks.org/wiki/C%2B%2B_Programming/RTTI
Why does C++ not have reflection?
您可以解析字符串,分离参数并将它们发送到函数,没有任何问题,但是您不能做的是在字符串上引用函数及其名称,因为该函数在运行时不再有名称。
您可以使用 if-else if 链来检查函数名称,然后解析参数并调用特定函数。
You could parse the string, separate the arguments and send them to the function with no problem, but what you cannot do is reference the function with its name on a string, because the function doesn't have a name anymore at runtime.
You could have a if-else if chain that checks for the function name, and then parse the arguments and call the specific function.
我修改了 @Xeo 的代码以正确使用 gcc,因此它确保以正确的顺序提取参数。我只是发布此内容,因为我花了一段时间才理解原始代码和命令执行中的拼接。全部功劳仍应归功于@Xeo。如果我发现我的实现有任何问题,我会回来进行编辑,但到目前为止,在我的测试中我还没有看到任何问题。
这也适用于 Visual Studio 2013,尚未尝试过早期版本。
I modified @Xeo's code to work with gcc properly, so it ensures the parameters are pulled in the right order. I'm only posting this since it took me a while to understand the original code and splice in the order-enforcement. Full credit should still go to @Xeo. If I find anything wrong with my implementation I'll come back and edit, but thus far in my testing I haven't seen any problems.
This also works with Visual Studio 2013, have not tried earlier versions.