gpt4 book ai didi

c++ - 如何将 CRTP 与可变参数模板一起使用?

转载 作者:行者123 更新时间:2023-11-30 02:56:11 25 4
gpt4 key购买 nike

假设最初我有以下使用 CRTP 的设计:

template<class Outputter> class Generator {
protected:
vector<int> v;
private:
void work(ostream& out) {
// perform first part of some complex operations on v
out << *static_cast<Outputter *>(this);
// perform second part of some complex operations on v
out << *static_cast<Outputter *>(this);
// many more ....
// perform some final actions
}
public:
Generator(unsigned length): v(length) {}
friend ostream& operator<<(ostream& out, Outputter&& generator) {
// perform some preparation work
work(out);
// perform some final actions
return out;
}
};

class SimpleDumpOutputter : public Generator<SimpleDumpOutputter> {
private:
unsigned count;
public:
SimpleDumpOutputter(unsigned length): Generator(length), count() {}
friend ostream& operator<<(ostream& out, SimpleDumpOutputter& outputter) {
out << "Step " << ++count << " of calculation: "
copy(outputter.v.begin(), outputter.v.end(), ostream_iterator<int>(out, " "));
out << endl;
return out;
}
};

class FancyOutputter : public Generator<FancyOutputter> { // create a graph using graphviz's dot language to visualise v
private:
// abbreviated
public:
FancyOutputter(unsigned length): Generator(length) {}
friend ostream& operator<<(ostream& out, FancyOutputter& outputter) {
// write statements to out
return out;
}
};

// some more different Outputters, for example an Outputter that creates a pretty LaTeX document

在这个设计中,有一个Generatorvector<int> v 执行复杂计算的 CRTP 类模板并使用其派生类的友好 operator<< 在计算的每个步骤/部分打印结果.

这是我想要实现的一个有趣的概念:我希望在一次执行中以多种格式输出。具体来说,我认为我可以做到:

template<class Outputters> class AggregateOutputter : public Generator<AggregateOutputter<Outputters...> > {
private:
static const unsigned outputter_count = sizeof...(Outputters);
typedef array<ostream *, outputter_count> DestArr;
DestArr destinations;
public:
AggregateOutputter(unsigned v_length, DestArr destinations): IsomerGenerator<AggregateOutputter<Outputters...> >(length), destinations(destinations) {}
friend ostream& operator<<(ostream&, AggregateOutputter& outputter); // first argument is dummy, because we would use the ostreams in destinations
}

这个想法是用户会使用,比如说,AggregateOutputter<SimpleDumpOutputter, FancyOutputter并用 array 构造对象两个ostream秒。每当Generator电话 operator<<在输出类上,AggregateOutputter将遍历 ostreamdestinationsOutputters 中的类型并调用类似于 *dest_iter << *static_cast<Outputter_Iter>(this); 的内容.

虽然我不确定这将如何工作。我不确定是否可以通过这种方式使用多重继承,是否可以在 array 之间“压缩”和一组参数化类型。有没有人了解这种情况?

最佳答案

我修改了您的原始设计。我认为生成器在调用输出运算符时进行大量计算至少可以说是令人惊讶的。同样对于你的 AggregateOutputter 输出忽略 << 的 ostream 参数也是令人惊讶的。此外,Outputter 与 Generator 没有 is-a 关系。

我试图将这些问题分开,但最终没有使用 CRTP,而是使用了可变参数模板,但我认为它可以满足您的需求。

http://ideone.com/xQrnW4

#include <vector>
#include <iostream>
#include <iterator>
#include <array>
using namespace std;

class Generator {
protected:
vector<int> v;
public:
Generator(unsigned length): v(length) {}

template<class Outputter>
void do_calculations_with_output(Outputter& out){
// perform first part of some complex operations on v
out.output(v);
// perform second part of some complex operations on v
out.output(v);
// perform some final actions
}

};

class SimpleDumpOutputter {
private:

ostream* out;
unsigned count;
public:
SimpleDumpOutputter(ostream& os): out(&os), count() {}
template<class C>
void output(const C& c) {
*out << "Step " << ++count << " of calculation: ";
copy(c.begin(),c.end(), ostream_iterator<int>(*out, " "));
*out << endl;
}
};

class FancyOutputter {
ostream* out;
int count;
public:
FancyOutputter(ostream& os): out(&os),count() {}
template<class C>
void output(const C& c) {
// create a graph using graphviz's dot language to ease visualisation of v
*out << "Step " << ++count << " of calculation: ";
*out << "Graphviz output\n";
}
};

template<class... Outputters> class AggregateOutputter : private Outputters... {
private:
template<class First, class... Rest>
struct output_helper{
template<class C>
static void do_output(AggregateOutputter* pthis,const C& c){
static_cast<First*>(pthis)->output(c);
output_helper<Rest...>::do_output(pthis,c);
}

};

template<class First>
struct output_helper<First>{
template<class C>
static void do_output(AggregateOutputter* pthis,const C& c){
static_cast<First*>(pthis)->output(c);
}

};
public:
template<class... Out>
AggregateOutputter( Out&... out): Outputters(out)...{}
template<class C>
void output(const C& c) {
output_helper<Outputters...>::do_output(this,c);
}

};
int main(){

AggregateOutputter<FancyOutputter,SimpleDumpOutputter> out(cout,cout);

Generator g(10);

g.do_calculations_with_output(out);

}

关于c++ - 如何将 CRTP 与可变参数模板一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15855031/

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