如何在不编写(多)代码的情况下进行打印,扫描,二进制写入和二进制读取

时间:2017-05-28 08:06:38

标签: c++ templates reflection io

我讨厌为我的c ++程序编写配置数据类:愚蠢的小数据类,带有一些标准函数:print()和scan(),有时是二进制read()和write(),通常是bind()将每个数据成员绑定到boost :: program_options :: options_description(这样我就可以从命令行或配置文件中设置配置数据)。

我已经初步尝试使用模板来减少编写这些课程的单调性,我想知道是否有人可以告诉我,如果我在重新投入时间之前重新发明轮子。我也想知道是否有任何人欣赏我尝试做的事情(而不是认为我完全疯了。)

基本思想是,不是写print(),scan(),read(),write()等,而是继承Print,Scan,Read和Write(我会调用服务类)因为缺乏一个更好的名称,它分别为我(通过双重调度)实现前面提到的方法,每个方法都按顺序打印,扫描,读取或写入每个数据成员的单调任务。当然,这些继承的方法执行速度比手工编写的方法要慢,但如果打印或扫描配置数据需要几微秒的时间,我真的不在乎。更重要的是,这些继承的类都没有添加数据(因此没有额外的开销来实例化或复制我的配置类的实例)。

我必须为一堂课做三件事才能使它全部运转:

  1. 为pure-virtual className()方法提供实现。
  2. 继承我想为我实现的接口类。
  3. 根据我选择的接口,我必须为每个数据成员包含一个或两个getter方法(一个const和一个非const)。
  4. 然后我还要写一个" Class"的部分模板专门化。描述我班级的班级。最后,必须将每个此类的实例加载到每个服务类(使用它们来确定如何处理类实例)。

    下面是一个main.cpp,希望能让你感受到我正在做的事情。让我知道你的想法。

    #include "Print.hpp"
    #include "Scan.hpp"
    #include "Write.hpp"
    #include "Read.hpp"
    
    using namespace std;
    
    class MyConfig : public Print, public Scan, public Write, public Read {
        public:
            const string className() const { return "MyConfig"; }
    
            const int&    i() const     { return _i; }
            const string& s() const     { return _s; }
    
            void i(int value)           { _i = value; }
            void s(const string& value) { _s = value; }
    
        private:
            int    _i;
            string _s;
    
            // The Scan and Read interfaces require a way to write the set
            // directly, hence these getter methods that return non-const
            // references.  I make these private, then define the friend below
            // so Scan and Read can get at them.
            //
            int&    i() { return _i; }
            string& s() { return _s; }
    
            template<class C, class P> friend class Class;
    };
    
    
    // Meta-class describing the members of class MyConfig and
    // how to get at them.
    //
    template<class P>
    class Class<MyConfig,P> : public ClassImpl<MyConfig,P> {
        public:
            Class() : ClassImpl<MyConfig,P>("MyConfig") {
                *this->template genMember<int>   ("i", &MyConfig::i, &MyConfig::i);
                *this->template genMember<string>("s", &MyConfig::s, &MyConfig::s);
            }
    };
    
    int main(int argc, char** argv) {
        try {
            // Each interface class is loaded with Class objects describing
            // user-data classes that use the interface.
            //
            Print::addClass<MyConfig>();
            Scan ::addClass<MyConfig>();
            Write::addClass<MyConfig>();
            Read ::addClass<MyConfig>();
    
            MyConfig x;
            x.i(3);
            x.s("abc");
    
            cout << "Printing config:\n" << x; // print x
            cout << "Scanning config:" << endl;
            cin  >> x; // scan x
            cout << "The scanned config was:" << endl;
            cout << x; // print x again
    
            cout << "Writing config to file." << endl;
            ofstream ofs;
            ofs.exceptions(ios::failbit | ios::badbit);
            ofs.open("testfile", ios::out | ios::binary);
            x.write(ofs); // write x to file in binary format
            ofs.close();
    
            cout << "Reading config back from file." << endl;
            MyConfig x2;
            ifstream ifs;
            ifs.exceptions(ios::failbit | ios::badbit | ios::eofbit);
            ifs.open("testfile", ios::in | ios::binary);
            x2.read(ifs); // read x from file in binary format
            ifs.close();
            cout << x2;
        }
        catch(const exception& x) {
            cerr << argv[0] << ":  " << x.what() << endl;
            return 1;
        }
        return 0;
    }
    

    节目输出:

    matt@dworkin:$ ./a.out
    Printing config:
    i = 3
    s = abc
    Scanning config:
    i=4
    s=xyz
    The scanned config was:
    i = 4
    s = xyz
    Writing config to file.
    Reading config back from file.
    i = 4
    s = xyz
    

0 个答案:

没有答案