在不知道参数的情况下传递模板

时间:2018-04-18 15:06:45

标签: c++ templates initializer-list

我是C ++的新手,我不确定我是否不知道如何做到这一点,或者我的方法是否完全错误。

我有一个处理阶段的管道:每个阶段获取某个维度的数据,转换它(可能会改变该维度),然后调用该数据的下一个阶段。这些维度在编译时是已知的并且实现为模板参数。方法setNext用于定义以下阶段。

template<unsigned int dimIn, unsigned int dimOut>
class Stage {
    void process(Data<dimIn> dataIn) {
        Data<dimOut> processed = // do something
        mNextStage.process(processed)
    }

    void setNext(Data<dimOut>) {
        // store pointer to next stage
    }
}

这可以按预期工作。为了分组几个阶段并简化它们的构造,我想创建一个可以传递不同阶段的Pipeline对象。问题是,阶段的输入/输出维度不相等,所以我不确定如何做到这一点:

template<unsigned int firstDimIn, unsigned int firstDimOut>
class Pipeline {
    void addStage(Stage<?,?> stage) {
        // template parameters of stage are unknown
    }
}

Pipeline也是一个模板,它的参数保存第一阶段的输入维度和最后一阶段的输出维度。

使用示例:

Stage<6,5> s1;
Stage<5,4> s2;
Stage<4,2> s3;

Pipeline<6,2> pipe;
pipe.addStage(s1);
pipe.addStage(s2);
pipe.addStage(s3);

不是使用.addStage()逐步构建管道,而是使用初始化列表:

Pipeline<6,2> pipe = {s1, s2, s3};

但我在那里遇到同样的问题。

1 个答案:

答案 0 :(得分:4)

您可以创建代理并在每add后返回一个新类型。这可以利用维度的编译时检查。

template<int NBeg, int NEnd> struct Stage {};

template<int N, int Saved>
struct PipelineBuilder {
    template<int M>
    PipelineBuilder<M, Saved>
    AddStage(Stage<N, M>) { return {}; }

    void done() {
        static_assert(Saved == N, "Incompatible dim");
    }
};

template<int NIn, int NOut>
struct Pipeline {
    PipelineBuilder<NIn, NOut> GetBuilder() { return {}; }
};

int main() {
    Stage<6,5> s1;
    Stage<5,4> s2;
    Stage<4,3> s3;

    Pipeline<6, 2> p;

    p
        .GetBuilder()
        .AddStage(s1)
        .AddStage(s2)
        .AddStage(s3)
        .done()
        ;
}