c++boostboost-type-erasure

Boost.TypeErasure `any` with a concept returning the same `any`?


Imagine a matrix type, implemented as a B.TE any and a series of structs representing ordinary matrices, etc. It has a set of operations, say, transpose, etc. transpose should return a matrix. Can this be implemented in B.TE? Something like:

BOOST_TYPE_ERASURE_FREE(transpose);

struct ordinary_matrix_impl {};

using matrix =
    any<mpl::vector<copy_constructible<>, has_transpose<matrix(_self&)>>>;

auto transpose(ordinary_matrix_impl&) {
  // ...
  return matrix(ordinary_matrix_impl(/*...*/));
}

But the using matrix = ... doesn't compile (error: 'matrix' was not declared in this scope).

Is there a solution?


Solution

  • Solved it. Just wrap the any in a struct (Compiler Explorer):

    #include <boost/mpl/vector.hpp>
    #include <boost/type_erasure/any.hpp>
    #include <boost/type_erasure/free.hpp>
    #include <iostream>
    
    namespace mpl = boost::mpl;
    using namespace boost::type_erasure;
    
    BOOST_TYPE_ERASURE_FREE(transpose);
    
    struct ordinary_matrix_impl {};
    struct symmetric_matrix_impl {};
    
    struct matrix {
        any<mpl::vector<copy_constructible<>, has_transpose<matrix(_self&)>>> impl;
    };
    
    auto transpose(matrix m) {
        return transpose(m.impl);
    }
    
    auto transpose(ordinary_matrix_impl& m) {
        std::cout << "make a new ordinary matrix\n";
        return matrix{ordinary_matrix_impl()};
    }
    
    auto transpose(symmetric_matrix_impl& m) {
        std::cout << "make a new diagonal matrix\n";
        return matrix{m};
    }
    
    auto main() -> int {
        {
            matrix m{ordinary_matrix_impl()};
            auto t = transpose(m);
        }
    
        {
            matrix m{symmetric_matrix_impl()};
            auto t = transpose(m);
        }
    
        return 0;
    }