Daniel Jour 的广泛链接答案 https://stackoverflow.com/a/32041381/2546289展示了如何通过打包和隐藏参数来实现boost::any
并且可能是一个更好的解决方案(但我没有完全理解它)。
作为替代方案,您可以使用可变参数函数 https://en.cppreference.com/w/cpp/utility/variadic如下例所示。
请对我的代码持保留态度,我遇到了一些限制,而且我不是该主题的专家:
- 您无法通过以下方式接收引用类型参数
...
- const 参数被提升为非常量参数(在我的测试中
const int
晋升为int
)
- 我认为可变参数函数存在安全风险。如果函数参数是由用户提供的,请检查/清理输入。
这是代码示例(请注意,我重命名为Virtual_Machine::assert
to Virtual_Machine::vmassert
to use assert
from <cassert>
):
#include <iostream>
#include <string>
#include <vector>
#include <cassert>
#include <cstdarg>
class Virtual_Machine
{
private:
std::string name;
public:
Virtual_Machine(std::string n) : name(n) {}
void clear(size_t nargs, ...){std::cout << "Clear " << name << std::endl;};
void dump(size_t nargs, ...){std::cout << "Dump" << std::endl;};
void vmassert(size_t nargs, ...)
{
va_list args;
va_start(args, nargs);
assert(nargs == 1);
const std::string value(va_arg(args, std::string));
std::cout << "Assert " << value << std:: endl;
va_end(args);
}
void push(size_t nargs, ...)
{
va_list args;
va_start(args, nargs);
assert(nargs == 2);
const int e(va_arg(args, int));
const std::string str(va_arg(args, std::string));
std::cout << "Push " << e << ", " << str << std:: endl;
va_end(args);
}
};
class Parser
{
private:
Virtual_Machine vm;
std::vector<std::string> commands;
std::vector<void (Virtual_Machine::*)(size_t, ...)> funcs;
public:
Parser(std::string vm_name) : vm(vm_name) {}
void add_func(
void (Virtual_Machine::* f)(size_t, ...),
std::string command)
{
commands.push_back(command);
funcs.push_back(f);
}
void prepare()
{
add_func(&Virtual_Machine::clear, "clear");
add_func(&Virtual_Machine::dump, "dump");
add_func(&Virtual_Machine::vmassert, "assert");
add_func(&Virtual_Machine::push, "push");
}
void test()
{
(vm.*(funcs[0]))(0);
(vm.*(funcs[1]))(0);
(vm.*(funcs[2]))(1, std::string("abc"));
(vm.*(funcs[3]))(2, 42, std::string("def"));
}
};
int main()
{
Parser a("vm_a");
a.prepare();
a.test();
return 0;
}
我把所有人的签名都改了Virtual_Machine
成员函数(size_t nargs, ...)
这样你就可以为所有可以用来声明的函数提供一个统一的类型Parser::funcs
。现在必须使用参数数量和后跟实际参数来调用每个函数。