2010-07-28 197 views
4

陣列的我已經一些代碼,產生一組TR1不同尺寸的陣列的::,但相同的類型,像陣列不同尺寸

array<int, 2> 
array<int, 4> 
array<int, 6> 

這些陣列的,並且它們的尺寸,都是在編譯時給出的,所以我確切地知道它們中會有多少,以及每一個的大小(但它們可能不同)。

問題:我想把它們放在一個集合中(使用數組<>會很棒),但是所有成員的類型必須相同,事實並非如此。

我想過使用boost :: variant,但是如何指定一個具有編譯時間確定類型列表的變體(我正在考慮預處理器的大量使用...)? 使用boost :: any怎麼樣?其他方法? (野生指針?)

TIA 〜秋

校正:預處理器不是在這種情況下可用的。

+0

'的std ::矢量'可能會是最簡單的。只是不要改變大小。誠然,它不完全相同,但它很乾淨。 – GManNickG 2010-07-28 00:17:56

+0

是的,我已經有一個使用std :: vector而不是tr1 :: array的實現,但是使用動態大小是毫無意義的,因爲它們可以在編譯時計算,所以我一直在尋找一個靜態解決方案。 – AkiRoss 2010-07-28 00:30:59

+0

你可能會喜歡其中一個容器:http://www.boost.org/doc/libs/1_43_0/libs/fusion/doc/html/fusion/container.html。另外,如果您想回復某人,請使用@,就像@aaa – Anycorn 2010-07-28 00:42:38

回答

3

我會使用Boost的MPL和Fusion庫。有兩種方法可以結束類型列表:生成它們,或明確定義它們。前者更靈活一些,但很難說哪種適合你,因爲我們不知道你是如何得到你的價值的。

在任何情況下,產生:

#include <boost/mpl/for_each.hpp> 
#include <boost/mpl/range_c.hpp> 
#include <boost/mpl/transform.hpp> 
#include <boost/mpl/vector.hpp> 
#include <array> 
#include <iostream> 

namespace bmpl = boost::mpl; 

// turns an index into an array 
template <typename T> 
struct make_array 
{ 
    // or whatever scheme you have 
    static const std::size_t size = T::value * 2; 

    // define generated type 
    typedef std::array<int, size> type; 
}; 

// list of values to convert 
typedef bmpl::range_c<size_t, 1, 10> array_range; 

// transform that list into arrays, into a vector 
typedef bmpl::transform<array_range, make_array<bmpl::_1>, 
          bmpl::back_inserter<bmpl::vector<>> 
           >::type array_collection; 

或明確指出:

#include <boost/mpl/vector.hpp> 
#include <array> 
#include <iostream> 

namespace bmpl = boost::mpl; 

// list all array types 
typedef bmpl::vector< 
      std::array<int, 2>, 
      std::array<int, 4>, 
      std::array<int, 6>, 
      std::array<int, 8>, 
      std::array<int, 10>, 
      std::array<int, 12>, 
      std::array<int, 14>, 
      std::array<int, 16>, 
      std::array<int, 18> 
       > array_collection; 

無論哪種方式,你可以使用它像這樣:

#include <boost/fusion/algorithm.hpp> 
#include <boost/fusion/container/vector.hpp> 
#include <boost/fusion/mpl.hpp> 
#include <boost/fusion/sequence.hpp> 
#include <boost/mpl/for_each.hpp> 
#include <typeinfo> 

// fusion "fuses" the bridge between MPL and runtime 
namespace bf = boost::fusion; 

struct print_type 
{ 
    template <typename T> 
    void operator()(const T&) const 
    { 
     std::cout << typeid(T).name() << "\n"; 
    } 
}; 

struct print_values 
{ 
    template <typename T> 
    void operator()(const T& pArray) const 
    { 
     std::cout << "Printing array with size " 
        << pArray.size() << ":\n"; 
     std::for_each(pArray.begin(), pArray.end(), 
       [](int pX) 
       { 
        std::cout << pX << " "; 
       }); 
     std::cout << std::endl; 
    } 
}; 

int main(void) 
{ 
    // print all the types you have 
    bmpl::for_each<array_collection>(print_type()); 
    std::cout.flush(); 

    // make a usable type out of the typelist 
    typedef bf::result_of::as_vector<array_collection>::type array_fusion; 
    array_fusion arrays; // now have an array of different arrays, 
         // compile-time generated but run-time usable 

    // access like this: 
    bf::at_c<0>(arrays)[1] = 5; 
    bf::at_c<1>(arrays)[2] = 7; 
    bf::at_c<2>(arrays)[0] = 135; 

    // for_each: 
    bf::for_each(arrays, print_values()); 
} 
+0

MPL似乎解決方案:)謝謝。 – AkiRoss 2010-07-28 15:37:23

+0

我總是很高興看到有關使用一些imho「高級」(或者也許只是「新」)boost文件庫(如mpl/fusion/proto/phoenix)的文章。有時候,我希望有更多關於偉大使用案例的帖子(甚至有一些關於這個問題的問題,但沒有太多答案)。但謝謝你的榜樣! – sascha 2011-04-03 13:55:01

0

您可以將不同類型的類放入STL容器的唯一方法是,如果容器包含指針(引用不工作,因爲它們不是默認可構造的),而是指向某個基類型,並且要收集的對象全部繼承從那種類型。請注意,從基類繼承的類型的容器(或任何模板類)不會從基類型的容器繼承。你可以使用void *,但是你需要做很多醜陋和危險的演員,你必須記得自己釋放內存。你爲什麼不寫一個固定大小的數組類,允許你在構造函數中設置大小?如果你寫作araray的包裝,它不應該是太多的工作。如果你想使用一些基於智能指針的解決方案,不要試圖使用auto_ptr,因爲STL容器的複製語義是錯誤的 - 請參閱boost shared_ptr。

0

你不會說你爲什麼要收集不同大小的靜態大小的數組。這很奇怪。爲什麼不使用動態大小的數組的集合?

你的選擇是:

  • 使用std ::載體,而不是性病:: TR1 ::陣列。

  • 存儲指向數組的指針和數組的大小。這看起來像這樣:std::vector<std::pair<int *, size_t> >。只要確保陣列的生命週期至少與載體的壽命一樣長!

  • 我希望boost :: variant也可以工作,但在實踐中使用會非常費力。

boost::variant<array<int, 2>, array<int, 4>, array<int, 6>, ... >