#c #opencv #templates #operator-overloading
#c #opencv #шаблоны #перегрузка оператора
Вопрос:
Я пытаюсь перегрузить оператор сдвига влево <<
для пользовательского класса, используя шаблон, и std::enable_if
использовать одно объявление и определение перегрузки как для вывода на консоль / печать, так и для записи в файл:
Foo.hpp
:
#include <iostream>
#include <fstream>
#include <type_traits>
// #include <opencv2/opencv.hpp>
namespace cv {
class Foo {
public:
Foo() { }
~Foo() { }
const int mb = 78;
static bool toFile(const Fooamp; instance);
};
}
template < typename OSTR_T,
typename = typename std::enable_if< std::is_base_of< std::ostream, OSTR_T >::value > >
OSTR_Tamp; operator<<(OSTR_Tamp; os, const cv::Fooamp; foo);
и Foo.cpp
:
#include "Foo.hpp"
#include <iostream>
#include <fstream>
namespace cv {
bool Foo::toFile(const Fooamp; instance) {
std::ofstream file("debug.txt", std::ios::app);
file << instance;
file.close();
return true;
}
} // namespace cv
template < typename OSTR_T, typename >
OSTR_Tamp; operator<<(OSTR_Tamp; os, const cv::Fooamp; foo) {
os << foo.mb << "n";
return os;
}
template std::ofstreamamp; operator<< < std::ofstream > (std::ofstreamamp;, const cv::Fooamp;);
template std::ostreamamp; operator<< < std::ostream > (std::ostreamamp;, const cv::Fooamp;);
Этот подход компилируется и работает нормально, однако мне нужно использовать несколько инструментов, предоставляемых OpenCV для расширения Foo
, а именно объявление некоторых cv::Point
и cv::Mat
членов.
Как ни странно, я обнаружил, что простого включения заголовка OpenCV opencv2/opencv.hpp
Foo.hpp
достаточно, чтобы код больше не компилировался, и компилятор по какой-то причине становится способным находить <<
перегрузку:
error: no match for ‘operator<<’ (operand types are ‘std::ofstream’ {aka ‘std::basic_ofstream<char>’} and ‘const cv::Foo’)
9 | file << instance;
| ~~~~ ^~ ~~~~~~~~
| | |
| | const cv::Foo
| std::ofstream {aka std::basic_ofstream<char>}
Я также заметил, что это происходит только в том случае, если я объявляю Foo в cv:: namespace . Что именно здесь происходит, как включение заголовка может создать такой конфликт?
Комментарии:
1. Помимо того, о чем вы спрашиваете, мне любопытно, чего вы ожидаете достичь, используя SFINAE таким образом, вместо простого объявления шаблона, который принимает a
std::ostream amp;
в качестве параметра?2. @SamVarshavchik Я на самом деле не понял, что
std::ofstream
это производное отstd::ostream
, и попытался использовать шаблонную перегрузку, чтобы соответствовать обоим. Сначала я начал с объявления перегрузки, как вы предлагаете, но получал ту же ошибку компиляции.3. Если вы не поняли, «что
std::ofstream
было получено изstd::ostream
«, то что именно привело вас к реализации SFINAE, который используетstd::is_base_of< std::ostream ... >
, который проверяет именно это? Что касается причины исходной ошибки, то, вероятно, это связано с тем, чтоcv
пространство имен определяет свою собственную<<
перегрузку, поэтому, как только поиск имени найдет его, он не будет пытаться выполнить разрешение перегрузки в глобальном пространстве имен. Перемещение вашей<<
перегрузки непосредственно вcv
пространство имен, скорее всего, решит эту проблему.