试图从肖恩父母的谈话中应用这种模式“继承是邪恶的基础”

时间:2017-08-27 20:37:20

标签: c++

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

以上只是伪代码......这是我到目前为止所做的。我从Sean Parents的谈话中大量借用,可以在这里找到消息来源。

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

Model :: print没有看到Object :: print函数,我不明白为什么。它似乎与链接的源代码类似,它可以在那里工作......

从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();
}
百万感谢!

2 个答案:

答案 0 :(得分:2)

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

#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类是实际的文档类,以及向量&lt;&gt;的位置。住了。根据我的理解,你的课堂应该是文件的载体,但它不能像写的那样做。

答案 1 :(得分:1)

所以,我抓住了你的整体问题。

以下代码编译。它复制了一些东西(我很懒),但它支持使用简单For生成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))交叉产品。

#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);
}