Repository: opencv
Issue: Templated vector/array conversion operators for cv::Mat exist but can't compile
Labels: feature,future

##### System information (version)

- OpenCV => 4.1.0
- Operating System / Platform => Ubuntu Linux 18.04
- Compiler => gcc 7.4

##### Detailed description

`cv::Mat` (and possibly other OpenCV data types) advertise conversion operators that don't actually compile.  This causes problems for code like logging or serialization libraries that use compile-time checks like `std::is_convertible<>` to try to pick a valid conversion for an arbitrary type.

The problem is that in `mat.inl.hpp`, `cv::Mat` defines "universal" conversion operators to *any* kind of `std::vector` or `std::array`:

```.cpp
template<typename _Tp> inline
Mat::operator std::vector<_Tp>() const
{
    std::vector<_Tp> v;
    copyTo(v);
    return v;
}

template<typename _Tp, std::size_t _Nm> inline
Mat::operator std::array<_Tp, _Nm>() const
{
    std::array<_Tp, _Nm> v;
    copyTo(v);
    return v;
}
```

This means that `std::is_convertible<cv::Mat, std::vector<*anything*>>::value` and `std::is_convertible<cv::Mat, std::array<*anything*, N>>::value` always resolve as `true`.  However, it's only possible to actually compile these templates with `_Tp` instantiated as some kind of reasonable numeric type (or at least something with a few key things like `operator=(double)` defined).

IMO these should use `std::enable_if` to only allow the conversion operators to be instantiated for types that meet some reasonable compile-time restrictions.

It might also be a good idea for these operators to be tagged `explicit`, but that may break existing code if it relies on implicit conversion to a `vector<double>` or `array<double, N>`.

##### Steps to reproduce

If you have `nlohmann-json` available, this fails:

```.cpp
cv::Mat testMatrix;
nlohmann::json asJson{testMatrix};
```

because it deduces to a constructor using `std::vector<bool>`, which doesn't actually compile.  In this case because `cv::InputArray` and `cv::OutputArray` explicitly `delete` the contructors for `std::vector<bool>`.

You can also use code like this to see that it reports the availability of conversions that don't actually work:

```.cpp
static void doStuffInts(std::vector<int> params)
{
    // ... do something with params
}

static void doStuffBools(std::vector<bool> params)
{
    // ... do something with params
}

struct FooStruct
{
    public:
    int val{1};
};

static void doStuffFoos(std::vector<FooStruct> params)
{
    // ... do something with params
}

...

cv::Mat testMatrix;

static_assert(std::is_convertible<decltype(testMatrix), std::vector<int>>::value, "I guess implicit conversion to std::vector<int> is okay...");
std::vector<int> asInts = static_cast<std::vector<int>>(testMatrix);
doStuffInts(testMatrix); // seems a little sus to me, but maybe okay.  Compiles and implicitly converts.

static_assert(std::is_convertible<decltype(testMatrix), std::vector<bool>>::value, "This shouldn't work!"); // but the static_assert passes
std::vector<bool> asBoolsDoesntCompile = static_cast<std::vector<bool>>(testMatrix); // this doesn't compile
doStuffBools(testMatrix); // tries to implicitly convert to std::vector<bool> and doesn't compile

static_assert(std::is_convertible<decltype(testMatrix), std::vector<FooStruct>>::value, "This REALLY shouldn't work"); // but the static_assert passes
std::vector<FooStruct> asFoosDoesntCompile = static_cast<std::vector<FooStruct>>(testMatrix); // this (obviously) doesn't compile
doStuffFoos(testMatrix); // tries to implicitly convert to std::vector<FooStruct> and also doesn't compile
```
##### Issue submission checklist

 - [x] I report the issue, it's not a question
 - [x] I checked the problem with documentation, FAQ, open issues,
       forum.opencv.org, Stack Overflow, etc and have not found solution
 - [ ] I updated to latest OpenCV version and the issue is still there
     `(I haven't done this but the operator definitions for cv::Mat have not changed)`
 - [x] There is reproducer code and related data files: videos, images, onnx, etc