ulidtko
ulidtko

Reputation: 15560

How to take a 2D view of Boost.MultiArray as an argument into function?

I have a 3D array of doubles. I want to write simple & generic function to print 2D slices of it.

Code:

#include <cstdio>
#include <boost/multi_array.hpp>

template<class M> // any model of MultiArray concept
void printFloatMatrix(typename M::template array_view<2u>::type matrix) {
    using std::printf;

    for(auto& row : matrix) {
        for(auto& elem : row) {
            printf("%5.3f ", elem);
        }
        printf("\n");
    }
}


int main() {
    typedef boost::multi_array<double,3> data_t;
    data_t test_matrix{data_t::extent_gen()[10][10][2]};
    // ...

    using boost::indices;
    using boost::multi_array_types::index_range;
    printFloatMatrix(test_matrix[ indices[index_range()] [index_range()] [0] ]);
}

With GCC this produces the error message:

test.cpp: In function ‘int main()’:
test.cpp:24:79: error: no matching function for call to ‘printFloatMatrix(boost::multi_array_ref<double, 3u>::array_view<2u>::type)’
test.cpp:24:79: note: candidate is:
test.cpp:5:6: note: template<class M> void printFloatMatrix(typename M::array_view<2u>::type)

Why the error?

Why doesn't M is inferred to be boost::multi_array_ref<double, 3u>?

How do I write the prototype that'd work?

Upvotes: 4

Views: 641

Answers (2)

alfC
alfC

Reputation: 16242

Sure, you have to constrain your arguments:

template<class M,
  std::enable_if_t<M::dimensionality == 2 and std::is_same_v<typename M::element, double>, int> =0
> 
void printFloatMatrix(const M& matrix)

Upvotes: 1

ulidtko
ulidtko

Reputation: 15560

I'm not able to spell the exact reason why C++ type inference fails here, but changing the function prototype to template<class M> void printFloatMatrix(const M& matrix) worked.

The prototype is uselessly wide now, though. With high chance it will bite me in the future. This situation will hopefully be fixed with the advent of concepts, or can alternatively be worked-around with static asserts.

Thanks to ##c++ at Freenode.

Upvotes: 1

Related Questions