尝试应用肖恩父母谈话"inheritance is the base class of evil"中的模式

Trying to apply the pattern from sean parent's talk "inheritance is the base class of evil"

本文关键字:class base of evil 模式 the inheritance 肖恩 应用 父母 is      更新时间:2023-10-16

https://ideone.com/1Pkxwe

我正在尝试在 c++ 中理解。我想从一些其他可迭代容器中构造一个For实例。稍后我将传递一个函数,For将对其内容调用该函数。

我还没有通过异构向量,但我正在想象

void f(int i, char c) {
cout << i << " " << c << endl;
}
For(1,2)('a','b').yield(f);

将打印

1 a
1 b
2 a
2 b

以上只是伪代码...这就是我目前所拥有的。我大量借鉴了肖恩父母的谈话,这个来源可以在这里找到。

https://raw.githubusercontent.com/boostcon/cppnow_presentations_2012/master/fri/value_semantics/value_semantics.cpp

模型::p rint 看不到 Object::p rint 函数,我不明白为什么。它似乎类似于链接的源代码,并且在那里工作......

来自 IDEONE 的错误输出

prog.cpp: In instantiation of ‘void Object::Model<T>::print() [with T = std::__cxx11::basic_string<char>]’:
prog.cpp:58:5:   required from here
prog.cpp:26:22: error: no matching function for call to ‘Object::Model<std::__cxx11::basic_string<char> >::print(std::__cxx11::basic_string<char>&)’
print(data);
~~~~~^~~~~~
prog.cpp:25:18: note: candidate: void Object::Model<T>::print() [with T = std::__cxx11::basic_string<char>]
void print() {
^~~~~
prog.cpp:25:18: note:   candidate expects 0 arguments, 1 provided
prog.cpp: In instantiation of ‘void Object::Model<T>::print() [with T = int]’:
prog.cpp:58:5:   required from here
prog.cpp:26:22: error: no matching function for call to ‘Object::Model<int>::print(int&)’
print(data);
~~~~~^~~~~~
prog.cpp:25:18: note: candidate: void Object::Model<T>::print() [with T = int]
void print() {
^~~~~
prog.cpp:25:18: note:   candidate expects 0 arguments, 1 provided

和代码

#include <vector>
#include <string>
#include <functional>
#include <iostream>
using namespace std;
struct Object {
template <typename T>
Object(T t) : model(new Model<T>(t)) {
cout << "construct object from T" << endl;
}
friend void print(string str) {
cout << str << endl;
}
friend void print(int i) {
cout << i << endl;
}
struct Concept {
virtual void print() =0;
};
template <typename T>
struct Model : Concept {
Model(T t) : data(t) {}
void print() {
print(data);
}
T data;
};
Concept *model;
};
struct For {
For() {
cout << "default construct For" << endl;
}
For(Object o) {
cout << "construct For from object and push back" << endl;
objects.push_back(o);
}
For operator()(Object o) {
cout << "push back object" << endl;
objects.push_back(o);
return *this;
}
void print() {
for(auto o : objects) {
o.model->print();
}
};
vector<Object> objects;
};
int main() {
auto heterogeneous = For(1)(string("hello"));
function<void(int)> f = [](int i)->void{ cout << i << endl; };
heterogeneous.print();
}

一百万感谢!

进行一些更改以使其编译。

#include <vector>
#include <string>
#include <functional>
#include <iostream>
using namespace std;
template <typename T>
void print(T&&);      // <- so that Object::Model knows what you want.
struct Object {
template <typename T>
Object(T t) : model(new Model<T>(t)) {
cout << "construct object from T" << endl;
}
friend void print(string str) {
cout << str << endl;
}
friend void print(int i) {
cout << i << endl;
}
struct Concept {
virtual ~Concept() = default;   // <- you MUST have a virtual dtor
virtual void print() =0;
};
template <typename T>
struct Model : Concept {
Model(T t) : data(t) {}
void print() {
::print(data);   // <-- the :: because Model::print hid what you wanted to call
}
T data;
};
Concept *model;
};

struct For {   // I don't recall this from Sean's talk.  I don't think it 
// works as intended.
For() {
cout << "default construct For" << endl;
}
For(Object o) {
cout << "construct For from object and push back" << endl;
objects.push_back(o);
}
For operator()(Object o) {
cout << "push back object" << endl;
objects.push_back(o);
return *this;
}
void print() {
for(auto o : objects) {
o.model->print();
}
};
vector<Object> objects;
};
// print functions for your types.
void print(const std::string& s)
{
std::cout << s << "n";
}
void print(const int& i)
{
std::cout << i << "n";
}
int main() {
auto heterogeneous = For(1)(string("hello"));  // this adds [1,"hello"] to the model
// is this what you want?
//function<void(int)> f = [](int i)->void{ cout << i << endl; };
heterogeneous.print();
}

在 Sean 的演讲中,你的 Object 类是什么是实际的文档类,这就是向量<>存在的地方。据我了解,你的 for class 应该是文档的载体,但它不能按照书面形式做到这一点。

所以,我试了一下你的整体问题。

编译以下代码。 它复制的东西有点多(我很懒),但它支持使用一个简单的For(a,b,c)(1,2,3)生成((a,1),(a,2),(a,3),(b,1),(b,2),(b,3),(c,1),(c,2),(c,3))进行For交叉产品。

#include <vector>
#include <string>
#include <functional>
#include <iostream>

// Default print; stream to cout:
template <typename T>
void print(T const& t){ std::cout << t <<"n"; }
// Functional-style loops:
struct Object;
// a loop-body is a "sink" of Objects.  In C++, it is the part after the control flow, the code
// that gets run each iteration.
using Body=std::function<void(Object)>;
// a loop is a "sink" of loop-bodies.  Read this as "loop over the contents of an Object, doing Body"
using Loop=std::function<void(Body)>;
// default foreach: return a loop that just visits yourself:
template <typename T>
Loop foreach(T const& t) {
return [t](Body body){ body(t); };
}
// custom printing:
inline void print(std::string const& str) {
std::cout << """ << str  <<""" << std::endl;
}
inline void print(int i) {
std::cout << "Integer: "<< i << std::endl;
}
// such custom prints can go here, or in the namespace of the type.
// Objects are actually smart pointers to type-erased data:
struct Object {
template <typename T>
Object(T t) : model(std::make_shared<Model<T>>(std::forward<T>(t))) {
//  std::cout << "construct object from T" << std::endl;
}
friend void print(Object o){
o.model->do_print();
}
friend Loop foreach(Object o){
return o.model->do_foreach();
}
struct Concept {
virtual void do_print() =0;
virtual Loop do_foreach() = 0;
// no dtor, as shared ptr handles that
};
template <typename T>
struct Model final : Concept {
Model(T t) : data(std::forward<T>(t)) {}
void do_print() override {
print(data); 
}
Loop do_foreach( ) override {
return foreach(data);
}
T data;
};
std::shared_ptr<Concept> model;
};

struct For {
For() {}
template<class...Ts>
For(Ts const&...ts):
objects({ts...})
{}
// given an Object o, return that object's contents
// in a For.
static For box(Object o) {
For tmp;
foreach(o)([&tmp](Object o){ tmp+=o; });
return tmp;
}
For(For const&)=default;
For& operator+=(Object o){ objects.push_back(o); return *this; }
For operator+(Object o) const { For tmp=*this; tmp+= o; return tmp; }
For operator*(For rhs)const{
For tmp;
for( auto o1 : objects )
for( auto o2 : rhs.objects )
{
tmp += box(o1) + o2;
}
return tmp;
}
For& operator*=(For rhs){
*this = *this*rhs;
return *this;
}
template<class...Ts>
For operator()(Ts const&... ts) {
*this *= For(ts...);
return *this;
}
friend Loop foreach(For const& f){
return [f](Body body){
for(auto o : f.objects) {
body(o);
}
};
}
friend void print(For f) {
std::cout << "{";
for(auto o : f.objects) {
print(o);
}
std::cout << "}n";
};
std::vector<Object> objects;
};

测试代码:

int main() {
auto a = For(std::string("hello"),42)(1,-1);
auto b = a;
b('a','b','c');
std::cout <<"a:n";
print(a);
std::cout <<"b:n";
print(b);
}
相关文章: