久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

第125講 DirectX11Frame(5)

 佛法與智慧 2016-09-27

這一講的內(nèi)容和我們的框架有些偏,,但是他實現(xiàn)基礎(chǔ)實現(xiàn)的一部分,,這一講的主題應(yīng)該叫巧用C 的異常機制配合模板元技巧將一定格式的字符串轉(zhuǎn)換到指定類型的tuple中。


大家都知道字符串是沒有類型的,,或者說他是一種更為一般的泛型,,凡是可以通過流序列化的對象即可轉(zhuǎn)換為字符的形式,比如“123”是可以轉(zhuǎn)換到double,同樣可以轉(zhuǎn)換到int等等,。而C 的tuple卻又是強類型的東西,,這兩者的區(qū)別可以是千差萬別,而我們今天的主題是要將兩者結(jié)合在一起,。


std::tuple_element<0,std::tuple<...>>::type

std::tuple_element<1,std::tuple<...>>::type


上面的方式是我們獲取tuple元素類型的方法,。下面進入主題。


    數(shù)據(jù)儲存在文本中那么都是字符串,,所以當(dāng)需要處理數(shù)據(jù)的時候需要將字符串轉(zhuǎn)換成相應(yīng)的類型,,這本來沒什么,只需要知道類型即可轉(zhuǎn)換,,那么如何將一個字符串轉(zhuǎn)換到指定類型的tuple中呢,?因為把參數(shù)放進數(shù)據(jù)放進tuple中有很多好處,簡單點說在操作lua函數(shù)中可以帶來很大的便利,,好吧,,就算不在C 中使用lua,那么統(tǒng)一管理數(shù)據(jù)也是很好的,,再比如在操縱函數(shù)過程中用來打包函數(shù)參數(shù)也是很好的.



    假如有一個函數(shù)需要int,,float,float的參數(shù),,而這些參數(shù)我們大概可能是從文件中讀取,,那么他們是字符串,通常一般大概都會這么做,,知道參數(shù)類型,,將字符串轉(zhuǎn)換成相應(yīng)的類型的數(shù)據(jù),然后調(diào)用函數(shù),,問題來了,,這樣硬編碼是不是真的很好呢?



void test(int i, double b){

std::cout << i << std::endl;

std::cout << b << std::endl;

}

double test(int i, double b,double c){

std::cout << i << std::endl;

std::cout << b << std::endl;

std::cout << c << std::endl;

return i*b*c;

}


        typedef double(*F)(int, double, double);

F __f = test;

std::string str;

std::cin>>str;

ManualFun(__f, str); // 使用輸入的參數(shù)調(diào)用函數(shù)


     如果我們想要達到上面的效果,,我們通常會根據(jù)函數(shù)特性來根據(jù)參數(shù)類型把字符串轉(zhuǎn)換到tuple,,在將tuple解包得到我們要的函數(shù)執(zhí)行所必須的參數(shù)即可,當(dāng)然這些都在內(nèi)部函數(shù)的調(diào)用中完成,,所以比較簡單,,這里就不多說,,下面我們來看看怎么將那個儲存參數(shù)的tuple提取出來,。

    嗯,為什么說把儲存參數(shù)的tuple提取出來需要拿出來說一下呢,?因為tuple的操作都是使用了大量的模板,,其實就是tuple就是一個跨越編譯期和運行期的一個模板元應(yīng)用,所以操作tuple不能像操作一般的容器對待,這是因為每一次操作tuple其實都是在操作一個臨時的類型不同的對象,。簡單點說,,你要檢查tuple的每一個數(shù)據(jù)的類型都是一個模板的不同實例化:

         

std::tuple_element<0,std::tuple<...>>::type

std::tuple_element<1,std::tuple<...>>::type

    同樣是獲取tuple中元素的類型,但是不同的元素就是使用tuple_element的不同實例化,,也就是說std::tuple_element<0,std::tuple<...>> 和 std::tuple_element<1,std::tuple<...>> 就像大圣和白龍馬一樣沒啥關(guān)系,。而問題是我們想要讓字符串轉(zhuǎn)換到指定的tuple中我們就要知道tuple中每一個元素的類型。所以,,這樣一來,,還是逃離不了使用模板元的節(jié)奏。

         

template<size_t index,size_t M,class T>

struct TypeConvert;


template<size_t index, size_t M, class ... Args>

struct TypeConvert<index, M, std::tuple<Args...>>{

typedef typename std::tuple_element<index, std::tuple<Args...>>::type Type;

template<class T>

struct Apply{

Apply(T t) :mT(t){}

inline void apply(std::vector<MString>& v)

{

MString str = v.front();

v.erase(v.begin());

auto tt = std::tuple_cat(mT, std::make_tuple(str.ToOtherType<Type>()));

TypeConvert<index 1, M, std::tuple<Args...>>::Apply<decltype(tt)>(tt).apply(v);

}

T mT;

};

};


template<size_t M,class ... Args>

struct TypeConvert<M,M,std::tuple<Args...>>{

typedef  typename std::tuple_element<M-1, std::tuple<Args...>>::type Type;

template<class T>

struct Apply{

Apply(T t) :mT(t){}

inline void apply(std::vector<MString>& v)

{

;

}

T mT;

};

};

template<class...Args>

std::tuple<Args...>& Totuple(const std::string& str, std::tuple<Args...>& output){

MString Mstr = str;

std::vector<MString> v;

Mstr.split(' \t', v);

if (v.size() < sizeof...(Args)){

return output;

}

TypeConvert<0, sizeof...(Args), std::tuple<Args...>>::Apply<std::tuple<>>(std::tuple<>()).apply(v);

return output;  // 這里不是我們想要的結(jié)果

}


    好吧,,到現(xiàn)在為止,,我們確實是將字符串的內(nèi)容轉(zhuǎn)換到tuple里面了,mT就是儲存結(jié)果的,,但是問題來了,,我們該怎么獲取這最后一個mT呢?

 

    當(dāng)然下面的使用方式是不可以的:

inline auto apply(std::vector<MString>& v)->decltype(...............)

{

return mT;

}


    就算通過各種技巧將返回類型給推導(dǎo)出來,,那代碼大概也是相當(dāng)難看的,,之所以不這么做,是因為可以很簡單的獲取我們想要的結(jié)果,,那就是異常,,只需要在遞歸終止時將結(jié)果當(dāng)做異常拋出來即可:

        

inline auto apply(std::vector<MString>& v)->decltype(...............)

{

throw mT;

}


    然后在ToTuple函數(shù)中抓一下異常:

template<class...Args>

std::tuple<Args...>& Totuple(const std::string& str, std::tuple<Args...>& output){

MString Mstr = str;

std::vector<MString> v;

Mstr.split(' \t', v); // 使用空格來或者\t來分隔字符串

     // MString是自己寫的一個字符串庫,使用boost里的算法也能夠完成這些操作

if (v.size() < sizeof...(Args)){

return output;

}

try{

TypeConvert<0, sizeof...(Args), std::tuple<Args...>>::Apply<std::tuple<>>(std::tuple<>()).apply(v);

}

catch (std::tuple<Args...> e){

output = std::forward<std::tuple<Args...>&&>(e);

return output;  // 這里就是我們想要的結(jié)果

}

catch (...){

return output; // 如果得到的結(jié)果不是我們想要的

}

}


     有木有覺得很巧妙呢,?在對輸出流操作符重載一下讓他可以接受輸入是不是更好呢,?

template<class...Args>

inline std::istream& operator>>(std::istream& is, std::tuple<Args...>& t){

std::string str;

std::getline(is, str);

if (str.empty())

return is;

t = Totuple(str, t);

return is;

}

          現(xiàn)在可以這么來對tuple進行操作,還能夠從文件中讀取數(shù)據(jù)并保存在指定的類型中:


std::tuple<int, float, float> t;

Totuple('10 20.3 30.5',t); 

std::cout << t << std::endl;

std::cin >> t;

std::cout << t << std::endl;

    


//============================================

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多