gpt4 book ai didi

c++ - 可变参数模板类中的派生(虚拟)函数参数

转载 作者:行者123 更新时间:2023-12-02 10:23:04 24 4
gpt4 key购买 nike

我正在构建一个解释器,并试图避免在实现内置函数时遇到一些样板。我可以通过使用模板来做到这一点。

以这个基本模板为例:

template<ast::builtin_type T>
class builtin_procedure abstract : public builtin_procedure_symbol
{
using arg_traits = builtin_type_traits<T>;

protected:
builtin_procedure(const symbol_identifier& identifier): builtin_procedure_symbol(identifier)
{
this->register_param(arg_traits::param_id(), T);
}

/**
* The actual implementation of the built-in function
*/
virtual void invoke_impl(typename arg_traits::builtin_type) = 0;

public:
void invoke(scope_context& procedure_scope) override
{
auto raw_arg = procedure_scope.memory->get(procedure_scope.symbols.get(arg_traits::param_id()));
this->invoke_impl(arg_traits::get_from_expression(raw_arg));
}
};

要实现采用字符串的内置函数,我只需要这样做:
class builtin_procedure_writeln final : public builtin_procedure<ast::builtin_type::string>
{
protected:
void invoke_impl(arg_traits::builtin_type arg) override;

public:
builtin_procedure_writeln();
}; /* Implementation in cpp file */


非常方便,我只需要实现虚拟的 invoke_impl方法即可。

我试图用可变数量的模板参数来实现此目标,因此如果我想在派生实现中支持2、3或更多参数(例如示例),则不必重复模板定义下面。

这将是上面的模板,以支持第二个模板参数:
template<ast::builtin_type T1, ast::builtin_type T2>
class builtin_procedure abstract : public builtin_procedure_symbol
{
using arg1_traits = builtin_type_traits<T1>;
using arg2_traits = builtin_type_traits<T2>;

protected:
builtin_procedure(const symbol_identifier& identifier): builtin_procedure_symbol(identifier)
{
this->register_param(arg_traits::param_id(1), T1);
this->register_param(arg_traits::param_id(2), T2);
}

/**
* The actual implementation of the built-in function
*/
virtual void invoke_impl(typename arg1_traits::builtin_type, typename arg2_traits::builtin_type) = 0;

public:
void invoke(scope_context& procedure_scope) override
{
auto raw_arg1 = procedure_scope.memory->get(procedure_scope.symbols.get(arg1_traits::param_id()));
auto raw_arg2 = procedure_scope.memory->get(procedure_scope.symbols.get(arg2_traits::param_id()));
this->invoke_impl(arg1_traits::get_from_expression(raw_arg1), arg2_traits::get_from_expression(raw_arg2));
}
};

我知道基本上可以通过模板递归来遍历每个模板参数来完成您想做的任何事情,但是虚拟 invoke_impl方法的定义呢?每个参数都从traits结构派生而来,使用模板递归似乎无法对方法本身进行调用。

如何(如果)可以使用可变参数模板在此基类上允许使用可变数量的参数,而不是仅使用更多模板参数复制/粘贴此基类?

最终的线索是n314159,它的工作原理是:
template<ast::builtin_type... Ts>
class builtin_procedure abstract : public builtin_procedure_symbol
{
private:
template<ast::builtin_type T>
typename builtin_type_traits<T>::builtin_type make_arg(scope_context& procedure_scope, int param_id)
{
auto raw_arg = procedure_scope.memory->get(procedure_scope.symbols.get(builtin_type_traits<T>::param_id(param_id++)));
return builtin_type_traits<T>::get_from_expression(raw_arg);
}

protected:
builtin_procedure(const symbol_identifier& identifier, ::symbol_table* runtime_symbol_table): builtin_procedure_symbol(identifier, runtime_symbol_table)
{
auto param_id = 0;

((void) this->register_param(builtin_type_traits<Ts>::param_id(++param_id), Ts), ...);
}

virtual void invoke_impl(typename builtin_type_traits<Ts>::builtin_type...) = 0;

public:
void invoke(scope_context& procedure_scope) override
{
auto param_id = 0;
this->invoke_impl(make_arg<Ts>(procedure_scope, ++param_id)...);
}
};

最佳答案

所以,我写了一个小例子。我认为没有人可以为可变参数模板做别名,所以我省略了它,但是即使它不太好,它也可以工作。因此,由于我无法使用非整体非类型模板参数,因此将ast::builtin_type切换为int,但是我认为您可以轻松地将其反转。以下编译(但显然没有链接^^)。

template<int i>
struct builtin_traits {
static int param_id(int) { return i;}
using builtin_type = int;
};

class builtin_procedure_symbol {
void register_param(int, int);
};

int get(int); // my replacement for procedure_scope.memory->get(procedure_scope.symbols.get

template<int... Ts>
class builtin_procedure : builtin_procedure_symbol{
builtin_procedure(): builtin_procedure_symbol()
{
((void) this->register_param(builtin_traits<Ts>::param_id(1), Ts), ... );
}

virtual void invoke_impl(typename builtin_traits<Ts>::builtin_type...) = 0;

void invoke()
{
auto f = [&](const auto& arg) {
auto raw_arg = get(builtin_traits<arg>::param_id());
return builtin_traits<arg>::get_from_expression(raw_arg);
};
this->invoke_impl(f(Ts)...);
}
};

希望对您有所帮助。如果不清楚,请询问。

关于c++ - 可变参数模板类中的派生(虚拟)函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59220292/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com