I am learning boost fusion and am trying to take a view of a std::vector<boost::fusion::vector<int,double,double> >
. The code appears simple but I appear to be running into some problems with const. I clearly misunderstand something about const and would love for someone to explain where I am going wrong.
The code:
template<int N, class T>
struct viewTraits{
typedef typename T::value_type etype;
typedef typename boost::fusion::result_of::as_nview<etype, N>::type netype;
typedef std::vector<netype> result_type;
};
template <int N, typename T>
typename viewTraits<N,T>::result_type c( T const &t )
{
typename viewTraits<N, T>::result_type retVal;
for (typename T::const_iterator it(t.begin());it<t.end();++it){
retVal.push_back(fusion::as_nview<N>(*it));
}
return retVal;
}
template <typename Container>
typename Container::value_type sum( Container const &container )
{
typedef typename Container::value_type value_type;
return std::accumulate( container.begin(), container.end(), value_type() );
}
int main(){
typedef fusion::vector<int, double, double> row;
typedef std::vector<row> container;
container x;
b( x, 200 );
std::cout << sum(c<1>(x)) << std::endl;
}
The code fails to compile at retVal.push_back()
because of an issue with casting const. I tried several permutations of removing and adding some const keywords but have not been successful at programming by permutation and would rather understand what I am doing.
Anyone have any thoughts? BTW the const
in the function definition of sum
and c
must stay.
EDIT: I forgot to mention that b
fills x
which is a std::vector<fusion::vector<int, double, double> >
EDIT2: The corrected code:
template<int N, class T>
struct viewTraits{
typedef typename T::value_type etype;
typedef typename fusion::result_of::as_nview<etype, N>::type netype;
typedef typename fusion::result_of::at_c<netype,0>::type reference;
typedef typename boost::decay<reference>::type value_type;
typedef std::vector<value_type> result_type;
};
template <int N, typename T>
typename viewTraits<N,T>::result_type c( T const &t )
{
typename viewTraits<N,T>::result_type retVal;
for(typename T::const_iterator it(t.begin()); it<t.end();++it){
retVal.push_back(fusion::deref(fusion::begin(fusion::as_nview<N>(*it))));
}
return retVal;
}
There are two immediate problems with your code:
you compute fusion::as_nview<N>(*it)
and try to store it as if it were a fusion::result_of::as_nview<T::value_type, N>::type
; in truth it is a fusion::result_of::as_nview<T::value_type const, N>::type
(*it
has type T::const_reference
); this is the source of your const
-related errors.
you try to accumulate the resulting views, but, as far I can tell from the Fusion docs, valid operations on such a view are mostly those of a Fusion Random Access Sequence. In particular you can't add two views together, or default construct one. Here's a lead to a possible fix (by no means the only way though), not actually tested:
typedef typename Container::value_type view_type;
typedef typename fusion::result_of::at_c<view_type, 0>::type reference;
// boost::decay is from Boost.TypeTraits
typedef typename boost::decay<reference>::type value_type;
value_type zero = 0;
return std::accumulate(container.begin(), container.end(), zero, add_views());
where add_views
is a functor that returns something in the spirit of lhs + at<0>(rhs)
. Note that this solution only really makes sense if you intend for c
to make views of length exactly one.