如何正确继承Halide::Generator派生类,避免抽象基类实例化及参数缺失问题
问题原因分析
第一个编译错误的根源
你定义的Base类直接继承了Halide::Generator<Base>,Halide的Generator模板机制会对所有继承了Halide::Generator<T>的类自动实例化内部的create()方法,该方法会尝试new一个T类型的实例,哪怕你没有注册Base类,这个模板实例化逻辑也会执行。而Base是包含纯虚函数的抽象类,无法被实例化,因此触发编译错误。
第二个参数缺失问题的根源
当你把Base改成非抽象类后,Halide的Generator参数是在模板实例化阶段静态收集的,你的派生类没有单独继承Halide::Generator<派生类类型>,因此派生类中定义的gain/offset参数不会被Halide的参数收集逻辑识别,最终生成的函数签名自然不会包含这些参数。
解决方案
采用模板化的基类+CRTP模式实现继承,避免基类被Halide的Generator机制实例化,同时保证派生类的参数能被正确收集。
修改后的my_generators.cpp代码
#include "Halide.h" #include <stdio.h> using namespace Halide; // 模板化的抽象基类,不继承Halide::Generator,不会被实例化 template<typename Derived> class Base { public: Input<Buffer<float>> input{"input", 2}; Output<Buffer<float>> output{"brighter", 2}; Var x, y; virtual Func process(Func input) = 0; void generate() { output = process(input); output.vectorize(x, 16).parallel(y); } }; class DerivedGain : public Halide::Generator<DerivedGain>, public Base<DerivedGain> { public: // 导入基类成员到当前作用域,避免名字查找失败 using Base<DerivedGain>::input; using Base<DerivedGain>::output; using Base<DerivedGain>::x; using Base<DerivedGain>::y; Input<float> gain{"gain"}; Func process(Func input) override { Func result("result"); result(x,y) = input(x,y) * gain; return result; } }; class DerivedOffset : public Halide::Generator<DerivedOffset>, public Base<DerivedOffset> { public: using Base<DerivedOffset>::input; using Base<DerivedOffset>::output; using Base<DerivedOffset>::x; using Base<DerivedOffset>::y; Input<float> offset{"offset"}; Func process(Func input) override { Func result("result"); result(x,y) = input(x,y) + offset; return result; } }; HALIDE_REGISTER_GENERATOR(DerivedGain, derived_gain) HALIDE_REGISTER_GENERATOR(DerivedOffset, derived_offset)
逻辑说明
- 基类修改为模板类,不再继承
Halide::Generator,不会触发Halide的实例化逻辑,纯虚函数的存在也不会导致编译错误。 - 每个派生类分别继承
Halide::Generator<自身类型>,完全符合Halide Generator的定义要求,派生类中定义的专属参数会被Halide的静态参数收集机制正确识别。 - 通过
using声明将基类成员导入派生类作用域,避免编译时名字查找失败。
修改后重新编译,生成的头文件会自动包含gain/offset参数,符合预期。
内容的提问来源于stack exchange,提问作者tuscasp
相关产品推荐
相关产品推荐

