Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does boost::multi_array's ConstMultiArrayConcept have a NumDims template argument?

I wrote an operator<< specialization that handles boost::multi_array, and used ConstMultiArrayConcept so that it would work on both the outer array and the sub-arrays. I'm wondering, though, why the multi_array concepts have a std::size_t NumDims template argument, since that can be simply extracted from the multi_array. The only use of NumDims in ConstMultiArrayConcept is as a recursion depth arg for idgen_helper, which tests slicing.

For reference, here's the header for multi_array concepts: http://www.boost.org/doc/libs/1_51_0/boost/multi_array/concept_checks.hpp

And here's my overloaded operator<<

template <typename CharT, typename Traits, typename MultiArrayT>
BOOST_CONCEPT_REQUIRES(
                       ((boost::multi_array_concepts::ConstMultiArrayConcept<MultiArrayT, MultiArrayT::dimensionality>)),
                       (std::basic_ostream<CharT, Traits>&)) // return type
operator <<( std::basic_ostream<CharT, Traits>& os, MultiArrayT const& ary )
{
    typename std::basic_ostream<CharT, Traits>::sentry opfx( os );

    if ( opfx ) {
        boost::multi_array_types::size_type const* sizes = ary.shape();
        // using Mathematica array notation
        os << "{";
        for ( int i = 0; i < sizes[0]; ++i ) {
            if ( i > 0 ) os << ", ";
            // verbose just to keep the types apparent
            typedef typename MultiArrayT::const_reference subType;
            subType item = ary[i];
            os << item;
        }
        os << "}\n";
    }
    return os;
}

This specialization works, but I must be missing something in my understanding. Any clues will be appreciated.

like image 680
Stonewall Ballard Avatar asked Aug 28 '12 16:08

Stonewall Ballard


1 Answers

Declaration of concept template class:

template <typename Array, std::size_t NumDims>  struct ConstMultiArrayConcept
{
...
};

See how ConstMultiArrayConcept is actually used in Boost code:

 template <typename T, std::size_t NumDims>
 class multi_array_ref {
   ...
   // Assignment from other ConstMultiArray types.
   template <typename ConstMultiArray>
   multi_array_ref& operator=(const ConstMultiArray& other)
   {
      function_requires< 
         detail::multi_array::
         ConstMultiArrayConcept<ConstMultiArray,NumDims> >();
      ...

The same code in multi_array_view& operator=() and sub_array& operator=() that take other ConstMultiArray type.

Looks like NumDims is not dimension number of passed array type Array, it's dimension number of outer array type that checks assignment compatibility with given other array type. So it could not be deduced from Array template parameter.

like image 194
Rost Avatar answered Nov 14 '22 23:11

Rost