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

问题描述 投票:1回答:1

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

以该基本模板为例:

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结构派生的,使用模板递归似乎也无法调用该方法本身。

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

c++ visual-c++ variadic-templates
1个回答
0
投票
所以,我写了一个小例子。我认为没有人可以为可变参数模板做别名,所以我省略了它,但是即使它不太好,它也可以工作。因此,由于我不能使用非整数非类型模板参数,因此将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)...); } };

希望对您有所帮助。如果不清楚,请询问。
© www.soinside.com 2019 - 2024. All rights reserved.