在非 C++11 環境中,簡化 return vector 的步驟

如果我們想建一個會 return 特定清單的 vector,直接依照 ex1 的寫法,在 VS 2012 中會無法支援 initialization list 的初始化,而造成 compile error :

ex1
std::vector<std::wstring> fruit_list()
{
  return {L"apple", L"pieapple", L"grape"}; // compile error: expected an expression
}

那我們就只好自已一個一個蓋 vector ,把它 push_back 進去:

ex2
std::vector<std::wstring> fruit_list()
{
    std::wstring v[] = {L"apple", L"pieapple", L"grape"};
    std::vector<std::wstring> result;
    result.push_back(v[0]);
    result.push_back(v[1]);
    result.push_back(v[2]);
    return result;    
}

又或者是可以利用 iterator 的特性,使用 vector 建構子能接收一對 beginend 的參數,來依序插入元素:

ex3
std::vector<std::wstring> fruit_list()
{
    std::wstring v[] = {L"apple", L"pieapple", L"grape"};
    std::vector<std::wstring> result(v, v + 3);
    return std::result;
}

再少一行定義 result 的 lvalue,直接回傳 vector :

ex4
std::vector<std::wstring> fruit_list()
{
    std::wstring v[] = {L"apple", L"pieapple", L"grape"};
    return std::vector<std::wstring>(v, v + 3);    
}

每次都要手寫陣列的大小很麻煩又容易錯,日後要再加入新元素又怕會忘記更新。但其實我們可以直接用 sizeof 問的,來讓 compiler 幫我們回傳 v[] 的元素個數:

ex5
std::vector<std::wstring> fruit_list()
{
    std::wstring v[] = {L"apple", L"pieapple", L"grape"};
    return std::vector<std::wstring>(v, v + sizeof v / sizeof v[0]); 
}

我們可以利用下面的 tool 來更簡化 make 一個 vector 的步驟。

handy tool
template <typename T, std::size_t N>
std::vector<T> make_vector(const T (&ary)[N])
{
   return std::vector<T>(ary, ary + N);
};

雖然說 vs 2012 沒辦法直接回傳一個大括號,來簡化寫的 code 。但是利用這個 handy tool ,可以只要多寫一個 定 type 用的 T v ,再將它傳到 make_vector,就可以達到回傳一個特定內容清單的 vector 的效果:

ex6
std::vector<std::wstring> fruit_list()
{
    std::wstring v[] = {L"apple", L"pieapple", L"grape"};
    return make_vector(v);
}
comments powered by Disqus