2013-04-12 46 views
4

我想通過BOOST_FUSION_ADAPT_TPL_STRUCT來迭代C++模板結構。我的結構包含大小爲模板參數的固定大小的多維數組。如果我們考慮將Boost的示例修改爲適合我的問題:BOOST_FUSION_ADAPT_TPL_STRUCT和模板數組大小

#include <iostream> 
#include <string> 
#include <boost/fusion/adapted/struct/adapt_struct.hpp> 
#include <boost/fusion/include/adapt_struct.hpp> 

// Example: 
// http://www.boost.org/doc/libs/1_53_0/libs/fusion/doc/html/fusion/adapted/adapt_tpl_struct.html 

namespace demo 
{ 
    template<typename T, unsigned int SIZE1, unsigned int SIZE2, typename Name, typename Age> 
    struct employee 
    { 
     Name name; 
     Age age; 
     T ar[SIZE1][SIZE2]; 
    }; 
} 

// Any instantiated demo::employee is now a Fusion sequence 
BOOST_FUSION_ADAPT_TPL_STRUCT(
    (T)(SIZE1)(SIZE2)(Name)(Age), 
    (demo::employee) (T)(SIZE1)(SIZE2)(Name)(Age), 
    (Name, name) 
    (Age, age) 
    (T, ar[SIZE1][SIZE2])) 

int main() 
{ 
    demo::employee<float, 2, 2, std::string, int> e; 
    e.name = "Bob"; 
    e.age = 25; 
    e.ar[0][0] = e.ar[1][0] = 0.1; 
    e.ar[0][1] = e.ar[1][1] = 0.2; 
} 

編譯失敗。而且,如果我們僅僅添加一個整型模板參數,而沒有將它用於數組大小,它也會失敗。

這是甚至可能與BOOST_FUSION_ADAPT_TPL_STRUCT?如果不是,我應該怎麼做呢?

回答

3

doc

序列(template_param0)(template_param1)...宣佈使用模板類型參數的名字。

雖然你有非類型模板參數SIZE

template<typename T, unsigned int SIZE, typename Name, typename Age> 
struct employee 

你可以將其轉換爲鍵入模板參數和使用boost::mpl::int_作爲包裝適合隨身攜帶的大小。您的代碼是compiled

template<int Size> 
struct Array 
{ 
    template<typename T> 
    struct Of 
    { 
     typedef T type[Size]; 
    }; 
}; 

namespace demo 
{ 
    template<typename T, typename SIZE, typename Name, typename Age> 
    struct employee 
    { 
     Name name; 
     Age age; 
     T ar[SIZE::value]; 
    }; 
} 

// Any instantiated demo::employee is now a Fusion sequence 
BOOST_FUSION_ADAPT_TPL_STRUCT(
    (T)(SIZE)(Name)(Age), 
    (demo::employee) (T)(SIZE)(Name)(Age), 
    (Name, name) 
    (Age, age) 
    (typename Array<SIZE::value>::template Of<T>::type, ar)) 

//... 
demo::employee<float, int_<2>, std::string, int> e; 
+0

好的,謝謝你的回答!我想我將不得不看看如果使用'BOOST_FUSION_ADAPT_TPL_STRUCT'值得在我的庫中進行一些重構。 – BenC

+0

不客氣!也許你還應該考慮['BOOST_FUSION_DEFINE_TPL_STRUCT'](http://www.boost.org/doc/libs/1_53_0/libs/fusion/doc/html/fusion/adapted/define_tpl_struct.html),以減少複製。 –

+0

我正在使用的數據結構用於使用CUDA進行GPGPU計算。我想我將不得不檢查'nvcc'是否可以正確處理這些Boost生成的結構。 – BenC

1

經過與Evgeny Panasyuk的長時間談話,我最終做了一些與衆不同的事情。由於我希望能夠對數據結構進行一些簡單的算術運算,因此我決定使用Eigen::Map而不是Boost::multi_array,因爲它提供了廣泛的操作符以及清晰的文檔。

因此,較高級別的循環由boost::fusion::for_each處理,較低級別的循環由Eigen處理。數組線性映射到特徵向量。尺寸通過data_eigen的構造函數傳遞。

#include <iostream> 

#include <boost/fusion/adapted/struct/adapt_struct.hpp> 
#include <boost/fusion/include/adapt_struct.hpp> 
#include <boost/fusion/algorithm/iteration/for_each.hpp> 
#include <boost/fusion/include/for_each.hpp> 
#include <boost/bind.hpp> 

#include <Eigen/Core> 

namespace demo 
{ 
template<typename T, int SIZE1, int SIZE2> 
struct data 
{ 
    T ar1[SIZE1][SIZE2]; 
    T ar2[SIZE1][SIZE2]; 
}; 

template<typename T> 
struct EigenMap 
{ 
    typedef Eigen::Map<Eigen::Matrix<T, Eigen::Dynamic, 1> > type; 
}; 

template<typename T> 
struct data_eigen 
{ 
    template <int SIZE1, int SIZE2> 
    data_eigen(data<T,SIZE1,SIZE2>& src) 
     : ar1(typename EigenMap<T>::type(&src.ar1[0][0], SIZE1*SIZE2)), 
      ar2(typename EigenMap<T>::type(&src.ar2[0][0], SIZE1*SIZE2)) 
    { 
    } 

    typename EigenMap<T>::type ar1; 
    typename EigenMap<T>::type ar2; 
}; 


struct print 
{ 
    template<typename T> 
    void operator()(const Eigen::Map<Eigen::Matrix<T, Eigen::Dynamic, 1> >& t) const 
    { 
     std::cout << t.transpose() << std::endl; 
    } 
}; 

struct scalarMult 
{ 
    template<typename T, typename U> 
    void operator()(T& t, U& u) const 
    { 
     t *= u; 
    } 
}; 

} 

BOOST_FUSION_ADAPT_TPL_STRUCT 
(
    (T), 
    (demo::data_eigen) (T), 
    (typename demo::EigenMap<T>::type, ar1) 
    (typename demo::EigenMap<T>::type, ar2) 
) 

int main() 
{ 
    typedef float REALTYPE; 
    const int SIZE1 = 2; 
    const int SIZE2 = 2; 

    // Basic data structure with multidimensional arrays 
    demo::data<REALTYPE, SIZE1, SIZE2> d; 
    for (unsigned int i = 0; i < SIZE1; ++i) 
     for (unsigned int j = 0; j < SIZE2; ++j) 
     { 
      d.ar1[i][j] = (i+1)*(j+1); 
      d.ar2[i][j] = i + j; 
     } 

    // Eigen::Map + BOOST_FUSION_ADAPT_TPL_STRUCT 
    demo::data_eigen<REALTYPE> eig_d(d); 

    std::cout << "d:" << std::endl; 
    boost::fusion::for_each(eig_d, demo::print()); 
    std::cout << std::endl; 

    boost::fusion::for_each(eig_d, boost::bind<void>(demo::scalarMult(), _1, 2.0)); 
    std::cout << "2 * d:" << std::endl; 
    boost::fusion::for_each(eig_d, demo::print()); 
    std::cout << std::endl; 
}