• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            天秤座的唐風(fēng)

            總會有一個(gè)人需要你的分享~!- 唐風(fēng) -

              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
              13 隨筆 :: 0 文章 :: 69 評論 :: 0 Trackbacks

            這兩天寫代碼,遇到這么一個(gè)模板決議的問題:
                有一個(gè)類 A,其中有兩個(gè)數(shù)據(jù)成員(方便起見都是 public )。為了從其它部分(比如文件)讀入數(shù)據(jù),我為 A 類重載了輸入流操作符。代碼如下所示:
            程序1

            typedef struct tagA {
                UINT32  biSize;
                UINT32  biCount;
            }
             A;

            template 
            <typename DataStream>
            DataStream
            & operator>>(DataStream& a_data, A& a_fileHeader)
            {        
                a_data
            >>a_fileHeader.biSize>>a_fileHeader.biCount;

                
            return a_data;        
            }


                一般使用標(biāo)準(zhǔn)IO流的話,這樣做至少在編譯上是沒有問題的(讀二進(jìn)制文件不行,后有補(bǔ)充)。
                在我的程序中,我目前只是測試時(shí)用文件讀取,到后期,肯定會換成其它形式(可能是直接大塊類似的數(shù)據(jù)整在一起,放在內(nèi)存中之類),所以我打算為數(shù)據(jù)源寫一個(gè)包裝類,在目前的階段,直接轉(zhuǎn)到標(biāo)準(zhǔn)IO文件讀取,后期再修改數(shù)據(jù)源類。因?yàn)槭褂脭?shù)據(jù)源類需要保持與標(biāo)準(zhǔn)IO的寫法一致( cin>>xx ),所以這個(gè)類要為每種基本類型重載輸入流操作符。這些重載的代碼結(jié)構(gòu)都是一樣的,只是數(shù)據(jù)類型不同,因此用模板是最好的,所以一開始,我寫成了下面這個(gè)樣子:
            程序2

            class DataFromFile
            {
            public:
                DataFromFile(CHAR 
            const *a_fileName)
                    :dataStream(a_fileName, std::ios::binary
            |std::ios::in)
                
            { assert(dataStream.good());}
                
            ~DataFromFile() 
                
            { dataStream.close();}
            public:
                template 
            <typename T>
                inline DataFromFile
            & operator>> (T& a_data)        
                
            {                                                  
                    dataStream.read((CHAR 
            *)&a_data, sizeof(T));   
                    
            return *this;                                     
                }

            private:
                std::fstream dataStream;
            }
            ;


                但在實(shí)際使用時(shí),像下面的語句,就發(fā)生了編譯問題:

            DataFromFile source("11.bin");
            A dest;
            source
            >>dest; 


                編譯器對這段代碼抱怨,說無法確定使用哪個(gè)模板……
                當(dāng)然,我是希望編譯器在這里使用程序一中的非成員模板函數(shù),然后在那個(gè)模板函數(shù)中,再用程序2中的成員模板函數(shù)來實(shí)例化基本類型的輸入操作。可是編譯器沒有這么智能,我理解,這里用A做模板參數(shù)的話,確實(shí)有二義性。
                想來想去沒想到好的辦法消除這種二義性,只好修改代碼,去掉其中一個(gè)的模板定義。類比地思考一下,標(biāo)準(zhǔn)IO并沒有發(fā)生這個(gè)問題,因?yàn)闃?biāo)準(zhǔn)IO的輸入流操作并不是模板函數(shù),而這里的DataFromFile類,明顯使用模板會比較優(yōu)雅,但二義性的問題不知道怎么解決。最后沒辦法,改成用宏來實(shí)現(xiàn),代碼如下:
            程序3

            #define InputForBuildIn(Type)                         \
            inline DataFromFile
            & operator>> (Type& a_data)        \
            {                                                     \
                dataStream.read((CHAR 
            *)&a_data, sizeof(Type));   \
                
            return *this;                                     \
            }


            class DataFromFile
            {
            public:
                DataFromFile(CHAR 
            const *a_fileName)
                    :dataStream(a_fileName, std::ios::binary
            |std::ios::in)
                
            { assert(dataStream.good());}
                
            ~DataFromFile() 
                
            { dataStream.close();}
            public:
                InputForBuildIn(INT8)
                InputForBuildIn(UINT8)
                InputForBuildIn(INT16)
                InputForBuildIn(UINT16)
                InputForBuildIn(INT32)
                InputForBuildIn(UINT32)
            private:
                std::fstream dataStream;
            }
            ;


                問題是沒有了,但總覺得不是滋味。(不知道有沒有更好的解決辦法?哪位大俠指點(diǎn)下?)


            PS:
                對 C++ 的標(biāo)準(zhǔn) IO 流還不熟,在以二進(jìn)制方式打開文件時(shí),使用 >> 操作符無法讀入數(shù)據(jù)?一開始的時(shí)候調(diào)了很久,后來才發(fā)現(xiàn)這里可能有問題,轉(zhuǎn)成使用 .read() 方法來讀數(shù)據(jù),就成功了。標(biāo)準(zhǔn) IO 還是得好好再補(bǔ)補(bǔ)啊。

            posted on 2009-06-28 12:01 唐風(fēng) 閱讀(750) 評論(7)  編輯 收藏 引用 所屬分類: 語言技術(shù)

            評論

            # re: 輸入流函數(shù)模板決議問題導(dǎo)致程序不簡潔 2009-11-15 03:54 OwnWaterloo
            沒辦法…… 讓它吃點(diǎn)虧好了:
            template <typename DataStream>
            DataStream& operator>>(DataStream& a_data, A& a_fileHeader);

            該成這樣:
            template<typename C,class T>
            std::basic_istream<C,T>& operator>>(std::basic_istream<C,T>& s,A& a);

            這也是為iostream寫擴(kuò)展時(shí)要考慮的一個(gè)問題:
            1. 要么嚴(yán)格使用標(biāo)準(zhǔn)庫中的(w)i(f/string)stream,basic_i(f/string)stream
            2. 要么放寬,使用任意重載了>>的。



            二進(jìn)制和文本關(guān)系到是否轉(zhuǎn)換換行模式。

            寫入文件時(shí)是怎么寫的?
            >>和<<是格式化輸出。
            read/write是非格式化輸出。
            12
            <<結(jié)果就是 '1','2' , >>時(shí)也希望是這樣
            write結(jié)果就是 0c,00,00,00, read時(shí)也希望是這樣。

              回復(fù)  更多評論
              

            # re: 輸入流函數(shù)模板決議問題導(dǎo)致程序不簡潔 2009-11-21 12:53 唐風(fēng)
            居然發(fā)現(xiàn) SFINAE 正是我要的解決方案~!
            后來試了一下下面這段實(shí)現(xiàn),就 OK 了……
             
            class DataFromFile
            {
            public:
                DataFromFile(
            char const *a_fileName)
                    :dataStream(a_fileName, std::ios::binary
            |std::ios::in)
                
            { assert(dataStream.good());}
                
            ~DataFromFile() 
                
            { dataStream.close();}
            public:
                template 
            <typename T> inline
                typename boost::disable_if
            <boost::is_class<T>, DataFromFile&>::type 
                
            operator>> (T& a_data)        
                
            {                                                  
                    dataStream.read((
            char *)&a_data, sizeof(T));   
                    
            return *this;                                     
                }

            private:
                std::fstream dataStream;
            }
            ;
             
            必須要贊一下 boost 的 enable_if ,確實(shí)是應(yīng)用 SFINAE 相當(dāng)優(yōu)雅的一種方式~!
             
            你的回復(fù)中對于輸入輸出流的解釋,我還是不太理解,呵呵,要學(xué)的東西真多哇,C++ 的 IO 流和 IO 流的本地化是我比較“恐懼”的部分。有沒有什么好庫可以代替?
            對于學(xué)習(xí)這塊,你有什么好的推薦?
             
             
              回復(fù)  更多評論
              

            # re: 輸入流函數(shù)模板決議問題導(dǎo)致程序不簡潔 2009-11-21 14:30 OwnWaterloo
            @唐風(fēng)
            這方法好,學(xué)習(xí)了~

            我覺得《the c++ programming language》中21章將流的架構(gòu)講得很清楚。
            具體實(shí)現(xiàn)么。。。
            有2本書可能有這方面的內(nèi)容,我沒細(xì)看……
            1本是《C++ Templates》
            1本是《標(biāo)準(zhǔn)C++輸入輸出流與本地化》
            http://www.china-pub.com/3274


            代替io流么…… 有個(gè)iconv可以做編碼轉(zhuǎn)換。
            代替io流的場合我沒遇見過……
            其實(shí)我對很多項(xiàng)目都要自己寫一個(gè)log模塊很不理解……
            沒往這方面想過……

              回復(fù)  更多評論
              

            # re: 輸入流函數(shù)模板決議問題導(dǎo)致程序不簡潔 2009-11-21 17:32 唐風(fēng)
            @OwnWaterloo
            謝謝推薦,說起來,C++ 的書讀了不少,不過 BS 老爺子的《the c++ programming language》還真是沒看過……慚愧,回頭找來啃一啃。
            《標(biāo)準(zhǔn)C++輸入輸出流與本地化》這本書看了前兩章都看不下去了,實(shí)在有點(diǎn)無趣,倒是《C++ standard library》中IO部分看幾回,但本地化還是沒搞明白。

            PS:
            說到 log 模塊,覺得還是蠻有用的,就現(xiàn)在手頭上做的項(xiàng)目來說,如果沒有這東西,所有模塊的 log 信息不受任何控制的話,光是這些 log 的通信就能把機(jī)器卡死(因?yàn)闄C(jī)器與PC的是串口連的)……
            覺得對于大一點(diǎn)的軟件(雖然我只接觸了一個(gè))來說,系統(tǒng)自身的調(diào)試機(jī)能和控制都蠻重要。  回復(fù)  更多評論
              

            # re: 輸入流函數(shù)模板決議問題導(dǎo)致程序不簡潔 2009-11-21 18:04 OwnWaterloo
            @唐風(fēng)
            C++老豆的書得看~_~ 確實(shí)是對C++理解最深的人。
            本地化在《TC++PL》的附錄(好像特別版才有附錄)中有,不過好像沒想象中的那么好用……


            關(guān)于log…… 特指debug log 我不是說它的效率…… 而是為什么需要這種東西……
            我的想法是,能測試就不要用調(diào)試器,能用調(diào)試器就不要寫debug log,只有不得已的時(shí)候,才會用那個(gè)東西。
            為什么不把bug都查出來?
            而是將它隱藏到軟件中,等它出現(xiàn)后 —— 交付給用戶使用后 —— 再從debug log中研究哪出的bug?

            當(dāng)然,我也沒什么大型軟件的經(jīng)驗(yàn),也沒有用戶邏輯復(fù)雜的軟件的經(jīng)驗(yàn)……
            可能那時(shí)候會理解debug log的用處……

              回復(fù)  更多評論
              

            # re: 輸入流函數(shù)模板決議問題導(dǎo)致程序不簡潔 2009-11-22 14:40 OwnWaterloo
            @唐風(fēng)
            后來又回味了一下,用SFINAE,故意讓使用某些類型實(shí)例化模板時(shí)產(chǎn)生錯(cuò)誤,從而從重載候選中剔除,確實(shí)是一個(gè)很好的辦法~_~

            boost的enable_if也確實(shí)抓住并滿足了大量需求。

            好東西啊,再回味回味...

              回復(fù)  更多評論
              

            # re: 輸入流函數(shù)模板決議問題導(dǎo)致程序不簡潔 2009-11-22 15:38 唐風(fēng)
            @OwnWaterloo
            是的啊,正好我也在“回味”,哈哈,準(zhǔn)備作為那篇 SFINAE 隨筆的補(bǔ)充,加一些 enable_if 的筆記……

            對于 enable_if 的還有一個(gè)比較舒服的功能點(diǎn)是:
            boost::disable_if<boost::is_class<T>, DataFromFile&>::type
            這個(gè)可以放返回值的位置上生效,并且讓條件滿足時(shí)使用DataFromFile&作為返回類型,其它情況下讓它 Substitution fail,而不對程序產(chǎn)生“負(fù)面影響”。

            真是非常體貼啊,因?yàn)樵谶@個(gè)地方,運(yùn)算符重載的參數(shù)個(gè)數(shù)是有限制的,不能隨意增加,所以在這里不能直接在參數(shù)表中加 T::* p = 0 之類的東西來運(yùn)用 SFINAE。


              回復(fù)  更多評論
              

            一本一道久久a久久精品综合 | 欧美久久亚洲精品| 7777久久亚洲中文字幕| 精品多毛少妇人妻AV免费久久| 久久91精品综合国产首页| 97精品伊人久久久大香线蕉| 久久精品aⅴ无码中文字字幕重口 久久精品a亚洲国产v高清不卡 | 久久久精品人妻一区二区三区蜜桃 | 国产成人久久激情91 | 91精品国产高清91久久久久久| 无码伊人66久久大杳蕉网站谷歌 | 久久久久无码精品| 久久人人爽人人爽AV片| 久久99精品久久久久久齐齐| 国产成人精品久久亚洲| 久久综合久久综合九色| 久久高潮一级毛片免费| 久久这里的只有是精品23| 精品国产99久久久久久麻豆| 久久久久99精品成人片试看| 国产午夜久久影院| 精品无码人妻久久久久久| 青春久久| 97久久超碰国产精品2021| 国产精品VIDEOSSEX久久发布| 久久精品国产一区二区三区不卡| 日韩va亚洲va欧美va久久| 国产精品久久久久久久久久影院| 五月丁香综合激情六月久久| 久久国产免费观看精品| 久久久久人妻一区精品| 久久久精品人妻一区二区三区四| 老司机国内精品久久久久| 一本色道久久88综合日韩精品 | 97精品依人久久久大香线蕉97 | 久久久精品人妻一区二区三区四| 亚洲精品国产成人99久久| 伊人色综合九久久天天蜜桃| 久久99精品久久久久子伦| 亚洲国产成人久久一区WWW| 韩国三级大全久久网站|