Now compiling under much more strigent warnings, with Clang and optional C++11 support

This commit is contained in:
hbristow 2013-06-29 14:24:53 -07:00
parent 53a7fbf74b
commit 538dbfe585
7 changed files with 62 additions and 51 deletions

View File

@ -32,6 +32,11 @@ set(OPENCV_EXTRA_EXE_LINKER_FLAGS "")
set(OPENCV_EXTRA_EXE_LINKER_FLAGS_RELEASE "") set(OPENCV_EXTRA_EXE_LINKER_FLAGS_RELEASE "")
set(OPENCV_EXTRA_EXE_LINKER_FLAGS_DEBUG "") set(OPENCV_EXTRA_EXE_LINKER_FLAGS_DEBUG "")
# if Apple and Clang, enable C++11 support :)
if(APPLE AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(OPENCV_EXTRA_CXX_FLAGS "-std=c++11 -stdlib=libc++")
endif()
macro(add_extra_compiler_option option) macro(add_extra_compiler_option option)
if(CMAKE_BUILD_TYPE) if(CMAKE_BUILD_TYPE)
set(CMAKE_TRY_COMPILE_CONFIGURATION ${CMAKE_BUILD_TYPE}) set(CMAKE_TRY_COMPILE_CONFIGURATION ${CMAKE_BUILD_TYPE})
@ -294,4 +299,4 @@ if(MSVC)
if(NOT ENABLE_NOISY_WARNINGS) if(NOT ENABLE_NOISY_WARNINGS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4251") #class 'std::XXX' needs to have dll-interface to be used by clients of YYY set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4251") #class 'std::XXX' needs to have dll-interface to be used by clients of YYY
endif() endif()
endif() endif()

View File

@ -58,7 +58,7 @@ set(HDR_PARSER_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../python/src2)
prepend("-I" MEX_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include) prepend("-I" MEX_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include)
prepend("-L" MEX_LIB_DIR ${CMAKE_BINARY_DIR}/lib) prepend("-L" MEX_LIB_DIR ${CMAKE_BINARY_DIR}/lib)
prepend("-l" MEX_LIBS opencv_core) prepend("-l" MEX_LIBS opencv_core)
set(MEX_OPTS "-largeArrayDims") set(MEX_OPTS -largeArrayDims)
if (ENABLE_SOLUTION_FOLDERS) if (ENABLE_SOLUTION_FOLDERS)
set_target_properties(${the_module} PROPERTIES FOLDER "Matlab bindings") set_target_properties(${the_module} PROPERTIES FOLDER "Matlab bindings")
@ -118,7 +118,7 @@ if (NOT MEX_WORKS)
${CMAKE_CURRENT_SOURCE_DIR}/test/test_compiler.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test/test_compiler.cpp
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/junk WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/junk
ERROR_VARIABLE MEX_ERROR ERROR_VARIABLE MEX_ERROR
OUTPUT_QUIET #OUTPUT_QUIET
) )
if (MEX_ERROR) if (MEX_ERROR)

View File

@ -12,9 +12,9 @@ def inputs(args):
except: except:
return [arg for arg in args if arg.I] return [arg for arg in args if arg.I]
def ninputs(args): def ninputs(fun):
'''Counts the number of input arguments in the input list''' '''Counts the number of input arguments in the input list'''
return len(inputs(args)) return len(inputs(fun.req)) + len(inputs(fun.opt))
def outputs(args): def outputs(args):
'''Determines whether any of the given arguments is an output '''Determines whether any of the given arguments is an output
@ -39,9 +39,9 @@ def void(arg):
def flip(arg): def flip(arg):
return not arg return not arg
def noutputs(args): def noutputs(fun):
'''Counts the number of output arguments in the input list''' '''Counts the number of output arguments in the input list'''
return len(outputs(args)) return int(not void(fun.rtp)) + len(outputs(fun.req)) + len(outputs(fun.opt))
def convertibleToInt(string): def convertibleToInt(string):
salt = '1+' salt = '1+'

View File

@ -29,6 +29,7 @@
// create a full function invocation // create a full function invocation
{%- macro generate(fun) -%} {%- macro generate(fun) -%}
{% if fun|ninputs or fun|noutputs %}
// unpack the arguments // unpack the arguments
{# ----------- Inputs ------------- #} {# ----------- Inputs ------------- #}
{% for arg in fun.req|inputs %} {% for arg in fun.req|inputs %}
@ -47,6 +48,7 @@
{% if not fun.rtp|void %} {% if not fun.rtp|void %}
{{fun.rtp}} retval; {{fun.rtp}} retval;
{% endif %} {% endif %}
{% endif %}
// call the opencv function // call the opencv function
// [out =] namespace.fun(src1, ..., srcn, dst1, ..., dstn, opt1, ..., optn); // [out =] namespace.fun(src1, ..., srcn, dst1, ..., dstn, opt1, ..., optn);
@ -60,6 +62,7 @@
mexErrMsgTxt("Uncaught exception occurred in {{fun.name}}"); mexErrMsgTxt("Uncaught exception occurred in {{fun.name}}");
} }
{% if fun|noutputs %}
// assign the outputs into the bridge // assign the outputs into the bridge
{% if not fun.rtp|void %} {% if not fun.rtp|void %}
outputs[0] = retval; outputs[0] = retval;
@ -70,5 +73,6 @@
{% for opt in fun.opt|outputs %} {% for opt in fun.opt|outputs %}
outputs[{{loop.index0 + fun.rtp|void|not + fun.req|outputs|length}}] = {{opt.name}}; outputs[{{loop.index0 + fun.rtp|void|not + fun.req|outputs|length}}] = {{opt.name}};
{% endfor %} {% endfor %}
{% endif %}
{% endmacro %} {% endmacro %}

View File

@ -26,26 +26,29 @@ using namespace cv;
* nrhs - number of input arguments * nrhs - number of input arguments
* prhs - pointers to input arguments * prhs - pointers to input arguments
*/ */
void mexFunction(int nlhs, mxArray* plhs[], void mexFunction(int nlhs, mxArray*{% if fun|noutputs %} plhs[]{% else %}*{% endif %},
int nrhs, const mxArray* prhs[]) { int nrhs, const mxArray*{% if fun|ninputs %} prhs[]{% else %}*{% endif %}) {
// assertions // assertions
conditionalError(nrhs >= {{fun.req|length - fun.req|only|outputs|length}}, "Too few required input arguments specified"); conditionalError(nrhs >= {{fun.req|length - fun.req|only|outputs|length}}, "Too few required input arguments specified");
conditionalError(nrhs <= {{fun.req|length + fun.opt|length - fun.req|only|outputs|length - fun.opt|only|outputs|length}}, "Too many input arguments specified"); conditionalError(nrhs <= {{fun.req|length + fun.opt|length - fun.req|only|outputs|length - fun.opt|only|outputs|length}}, "Too many input arguments specified");
conditionalError(nlhs <= {{ fun.rtp|void|not + fun.req|outputs|length + fun.opt|outputs|length}}, "Too many output arguments specified"); conditionalError(nlhs <= {{ fun.rtp|void|not + fun.req|outputs|length + fun.opt|outputs|length}}, "Too many output arguments specified");
{% if fun|ninputs or fun|noutputs %}
// setup // setup
{% if fun|ninputs %}
std::vector<Bridge> inputs(prhs, prhs+nrhs); std::vector<Bridge> inputs(prhs, prhs+nrhs);
{% set noutputs = fun.rtp|void|not + fun.req|outputs|length + fun.opt|outputs|length %} {% endif -%}
{%- if noutputs %} {%- if fun|noutputs %}
std::vector<Bridge> outputs({{noutputs}}); std::vector<Bridge> outputs({{fun|noutputs}});
{% endif %}
{% endif %} {% endif %}
{{ functional.generate(fun) }} {{ functional.generate(fun) }}
{%- if noutputs %} {%- if fun|noutputs %}
// push the outputs back to matlab // push the outputs back to matlab
for (size_t n = 0; n < nlhs; ++n) { for (size_t n = 0; n < static_cast<size_t>(nlhs); ++n) {
plhs[n] = outputs[n].toMxArray().releaseOwnership(); plhs[n] = outputs[n].toMxArray().releaseOwnership();
} }
{% endif %} {% endif %}

View File

@ -6,7 +6,7 @@
#include <string> #include <string>
#include <opencv2/core.hpp> #include <opencv2/core.hpp>
#include <opencv2/calib3d.hpp> #include <opencv2/calib3d.hpp>
#include <ext/hash_map> #include <unordered_map>
/* /*
* All recent versions of Matlab ship with the MKL library which contains * All recent versions of Matlab ship with the MKL library which contains
@ -208,7 +208,7 @@ private:
// this function is called exclusively from constructors!! // this function is called exclusively from constructors!!
template <typename Scalar> template <typename Scalar>
void fromMat(const cv::Mat& mat) { void fromMat(const cv::Mat& mat) {
mwSize dims[] = { mat.rows, mat.cols, mat.channels() }; mwSize dims[] = { static_cast<mwSize>(mat.rows), static_cast<mwSize>(mat.cols), static_cast<mwSize>(mat.channels()) };
ptr_ = mxCreateNumericArray(3, dims, Matlab::Traits<Scalar>::ScalarType, Matlab::Traits<>::Real); ptr_ = mxCreateNumericArray(3, dims, Matlab::Traits<Scalar>::ScalarType, Matlab::Traits<>::Real);
owns_ = true; owns_ = true;
switch (mat.depth()) { switch (mat.depth()) {
@ -412,28 +412,28 @@ cv::Mat MxArray::toMat<Matlab::InheritType>() const {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
template <typename InputScalar, typename OutputScalar> template <typename InputScalar, typename OutputScalar>
void deepCopyAndTranspose(const cv::Mat& src, MxArray& dst) { void deepCopyAndTranspose(const cv::Mat&, MxArray&) {
} }
template <typename InputScalar, typename OutputScalar> template <typename InputScalar, typename OutputScalar>
void deepCopyAndTranspose(const MxArray& src, cv::Mat& dst) { void deepCopyAndTranspose(const MxArray&, cv::Mat&) {
} }
template <> template <>
void deepCopyAndTranspose<float, float>(const cv::Mat& src, MxArray& dst) { void deepCopyAndTranspose<float, float>(const cv::Mat&, MxArray&) {
} }
template <> template <>
void deepCopyAndTranspose<double, double>(const cv::Mat& src, MxArray& dst) { void deepCopyAndTranspose<double, double>(const cv::Mat&, MxArray&) {
} }
template <> template <>
void deepCopyAndTranspose<float, float>(const MxArray& src, cv::Mat& dst) { void deepCopyAndTranspose<float, float>(const MxArray&, cv::Mat&) {
// use mkl // use mkl
} }
template <> template <>
void deepCopyAndTranspose<double, double>(const MxArray& src, cv::Mat& dst) { void deepCopyAndTranspose<double, double>(const MxArray&, cv::Mat& ) {
// use mkl // use mkl
} }
@ -535,7 +535,7 @@ public:
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// MATLAB TYPES // MATLAB TYPES
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
Bridge& operator=(const mxArray* obj) { return *this; } Bridge& operator=(const mxArray*) { return *this; }
Bridge(const mxArray* obj) : ptr_(obj) {} Bridge(const mxArray* obj) : ptr_(obj) {}
MxArray toMxArray() { return ptr_; } MxArray toMxArray() { return ptr_; }
@ -548,29 +548,29 @@ public:
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// --------------------------- string -------------------------------------- // --------------------------- string --------------------------------------
Bridge& operator=(const std::string& obj) { return *this; } Bridge& operator=(const std::string& ) { return *this; }
std::string toString() { std::string toString() {
return ptr_.toString(); return ptr_.toString();
} }
operator std::string() { return toString(); } operator std::string() { return toString(); }
// --------------------------- bool -------------------------------------- // --------------------------- bool --------------------------------------
Bridge& operator=(const bool& obj) { return *this; } Bridge& operator=(const bool& ) { return *this; }
bool toBool() { return 0; } bool toBool() { return 0; }
operator bool() { return toBool(); } operator bool() { return toBool(); }
// --------------------------- double -------------------------------------- // --------------------------- double --------------------------------------
Bridge& operator=(const double& obj) { return *this; } Bridge& operator=(const double& ) { return *this; }
double toDouble() { return ptr_.scalar<double>(); } double toDouble() { return ptr_.scalar<double>(); }
operator double() { return toDouble(); } operator double() { return toDouble(); }
// --------------------------- float --------------------------------------- // --------------------------- float ---------------------------------------
Bridge& operator=(const float& obj) { return *this; } Bridge& operator=(const float& ) { return *this; }
float toFloat() { return ptr_.scalar<float>(); } float toFloat() { return ptr_.scalar<float>(); }
operator float() { return toFloat(); } operator float() { return toFloat(); }
// --------------------------- int -------------------------------------- // --------------------------- int --------------------------------------
Bridge& operator=(const int& obj) { return *this; } Bridge& operator=(const int& ) { return *this; }
int toInt() { return ptr_.scalar<int>(); } int toInt() { return ptr_.scalar<int>(); }
operator int() { return toInt(); } operator int() { return toInt(); }
@ -583,57 +583,57 @@ public:
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// --------------------------- cv::Mat -------------------------------------- // --------------------------- cv::Mat --------------------------------------
Bridge& operator=(const cv::Mat& obj) { return *this; } Bridge& operator=(const cv::Mat& ) { return *this; }
cv::Mat toMat() const { return ptr_.toMat<Matlab::InheritType>(); } cv::Mat toMat() const { return ptr_.toMat<Matlab::InheritType>(); }
operator cv::Mat() const { return toMat(); } operator cv::Mat() const { return toMat(); }
// -------------------------- Point -------------------------------------- // -------------------------- Point --------------------------------------
Bridge& operator=(const cv::Point& obj) { return *this; } Bridge& operator=(const cv::Point& ) { return *this; }
cv::Point toPoint() const { return cv::Point(); } cv::Point toPoint() const { return cv::Point(); }
operator cv::Point() const { return toPoint(); } operator cv::Point() const { return toPoint(); }
// -------------------------- Point2f ------------------------------------ // -------------------------- Point2f ------------------------------------
Bridge& operator=(const cv::Point2f& obj) { return *this; } Bridge& operator=(const cv::Point2f& ) { return *this; }
cv::Point2f toPoint2f() const { return cv::Point2f(); } cv::Point2f toPoint2f() const { return cv::Point2f(); }
operator cv::Point2f() const { return toPoint2f(); } operator cv::Point2f() const { return toPoint2f(); }
// -------------------------- Point2d ------------------------------------ // -------------------------- Point2d ------------------------------------
Bridge& operator=(const cv::Point2d& obj) { return *this; } Bridge& operator=(const cv::Point2d& ) { return *this; }
cv::Point2d toPoint2d() const { return cv::Point2d(); } cv::Point2d toPoint2d() const { return cv::Point2d(); }
operator cv::Point2d() const { return toPoint2d(); } operator cv::Point2d() const { return toPoint2d(); }
// -------------------------- Size --------------------------------------- // -------------------------- Size ---------------------------------------
Bridge& operator=(const cv::Size& obj) { return *this; } Bridge& operator=(const cv::Size& ) { return *this; }
cv::Size toSize() const { return cv::Size(); } cv::Size toSize() const { return cv::Size(); }
operator cv::Size() const { return toSize(); } operator cv::Size() const { return toSize(); }
// -------------------------- Moments -------------------------------------- // -------------------------- Moments --------------------------------------
Bridge& operator=(const cv::Moments& obj) { return *this; } Bridge& operator=(const cv::Moments& ) { return *this; }
cv::Moments toMoments() const { return cv::Moments(); } cv::Moments toMoments() const { return cv::Moments(); }
operator cv::Moments() const { return toMoments(); } operator cv::Moments() const { return toMoments(); }
// -------------------------- Scalar -------------------------------------- // -------------------------- Scalar --------------------------------------
Bridge& operator=(const cv::Scalar& obj) { return *this; } Bridge& operator=(const cv::Scalar& ) { return *this; }
cv::Scalar toScalar() { return cv::Scalar(); } cv::Scalar toScalar() { return cv::Scalar(); }
operator cv::Scalar() { return toScalar(); } operator cv::Scalar() { return toScalar(); }
// -------------------------- Rect ----------------------------------------- // -------------------------- Rect -----------------------------------------
Bridge& operator=(const cv::Rect& obj) { return *this; } Bridge& operator=(const cv::Rect& ) { return *this; }
cv::Rect toRect() { return cv::Rect(); } cv::Rect toRect() { return cv::Rect(); }
operator cv::Rect() { return toRect(); } operator cv::Rect() { return toRect(); }
// ---------------------- RotatedRect --------------------------------------- // ---------------------- RotatedRect ---------------------------------------
Bridge& operator=(const cv::RotatedRect& obj) { return *this; } Bridge& operator=(const cv::RotatedRect& ) { return *this; }
cv::RotatedRect toRotatedRect() { return cv::RotatedRect(); } cv::RotatedRect toRotatedRect() { return cv::RotatedRect(); }
operator cv::RotatedRect() { return toRotatedRect(); } operator cv::RotatedRect() { return toRotatedRect(); }
// ---------------------- TermCriteria -------------------------------------- // ---------------------- TermCriteria --------------------------------------
Bridge& operator=(const cv::TermCriteria& obj) { return *this; } Bridge& operator=(const cv::TermCriteria& ) { return *this; }
cv::TermCriteria toTermCriteria() { return cv::TermCriteria(); } cv::TermCriteria toTermCriteria() { return cv::TermCriteria(); }
operator cv::TermCriteria() { return toTermCriteria(); } operator cv::TermCriteria() { return toTermCriteria(); }
// ---------------------- RNG -------------------------------------- // ---------------------- RNG --------------------------------------
Bridge& operator=(const cv::RNG& obj) { return *this; } Bridge& operator=(const cv::RNG& ) { return *this; }
/*! @brief explicit conversion to cv::RNG() /*! @brief explicit conversion to cv::RNG()
* *
* Converts a bridge object to a cv::RNG(). We explicitly assert that * Converts a bridge object to a cv::RNG(). We explicitly assert that
@ -654,42 +654,42 @@ public:
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// -------------------- vector_Mat ------------------------------------------ // -------------------- vector_Mat ------------------------------------------
Bridge& operator=(const vector_Mat& obj) { return *this; } Bridge& operator=(const vector_Mat& ) { return *this; }
vector_Mat toVectorMat() { return vector_Mat(); } vector_Mat toVectorMat() { return vector_Mat(); }
operator vector_Mat() { return toVectorMat(); } operator vector_Mat() { return toVectorMat(); }
// --------------------------- vector_int ---------------------------------- // --------------------------- vector_int ----------------------------------
Bridge& operator=(const vector_int& obj) { return *this; } Bridge& operator=(const vector_int& ) { return *this; }
vector_int toVectorInt() { return vector_int(); } vector_int toVectorInt() { return vector_int(); }
operator vector_int() { return toVectorInt(); } operator vector_int() { return toVectorInt(); }
// --------------------------- vector_float -------------------------------- // --------------------------- vector_float --------------------------------
Bridge& operator=(const vector_float& obj) { return *this; } Bridge& operator=(const vector_float& ) { return *this; }
vector_float toVectorFloat() { return vector_float(); } vector_float toVectorFloat() { return vector_float(); }
operator vector_float() { return toVectorFloat(); } operator vector_float() { return toVectorFloat(); }
// --------------------------- vector_Rect --------------------------------- // --------------------------- vector_Rect ---------------------------------
Bridge& operator=(const vector_Rect& obj) { return *this; } Bridge& operator=(const vector_Rect& ) { return *this; }
vector_Rect toVectorRect() { return vector_Rect(); } vector_Rect toVectorRect() { return vector_Rect(); }
operator vector_Rect() { return toVectorRect(); } operator vector_Rect() { return toVectorRect(); }
// --------------------------- vector_KeyPoint ----------------------------- // --------------------------- vector_KeyPoint -----------------------------
Bridge& operator=(const vector_KeyPoint& obj) { return *this; } Bridge& operator=(const vector_KeyPoint& ) { return *this; }
vector_KeyPoint toVectorKeyPoint() { return vector_KeyPoint(); } vector_KeyPoint toVectorKeyPoint() { return vector_KeyPoint(); }
operator vector_KeyPoint() { return toVectorKeyPoint(); } operator vector_KeyPoint() { return toVectorKeyPoint(); }
// --------------------------- vector_String ------------------------------- // --------------------------- vector_String -------------------------------
Bridge& operator=(const vector_String& obj) { return *this; } Bridge& operator=(const vector_String& ) { return *this; }
vector_String toVectorString() { return vector_String(); } vector_String toVectorString() { return vector_String(); }
operator vector_String() { return toVectorString(); } operator vector_String() { return toVectorString(); }
// ------------------------ vector_Point ------------------------------------ // ------------------------ vector_Point ------------------------------------
Bridge& operator=(const vector_Point& obj) { return *this; } Bridge& operator=(const vector_Point& ) { return *this; }
vector_Point toVectorPoint() { return vector_Point(); } vector_Point toVectorPoint() { return vector_Point(); }
operator vector_Point() { return toVectorPoint(); } operator vector_Point() { return toVectorPoint(); }
// ------------------------ vector_uchar ------------------------------------ // ------------------------ vector_uchar ------------------------------------
Bridge& operator=(const vector_uchar& obj) { return *this; } Bridge& operator=(const vector_uchar& ) { return *this; }
vector_uchar toVectorUchar() { return vector_uchar(); } vector_uchar toVectorUchar() { return vector_uchar(); }
operator vector_uchar() { return toVectorUchar(); } operator vector_uchar() { return toVectorUchar(); }
@ -702,17 +702,17 @@ public:
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// --------------------------- Ptr_StereoBM ----------------------------- // --------------------------- Ptr_StereoBM -----------------------------
Bridge& operator=(const Ptr_StereoBM& obj) { return *this; } Bridge& operator=(const Ptr_StereoBM& ) { return *this; }
Ptr_StereoBM toPtrStereoBM() { return Ptr_StereoBM(); } Ptr_StereoBM toPtrStereoBM() { return Ptr_StereoBM(); }
operator Ptr_StereoBM() { return toPtrStereoBM(); } operator Ptr_StereoBM() { return toPtrStereoBM(); }
// --------------------------- Ptr_StereoSGBM --------------------------- // --------------------------- Ptr_StereoSGBM ---------------------------
Bridge& operator=(const Ptr_StereoSGBM& obj) { return *this; } Bridge& operator=(const Ptr_StereoSGBM& ) { return *this; }
Ptr_StereoSGBM toPtrStereoSGBM() { return Ptr_StereoSGBM(); } Ptr_StereoSGBM toPtrStereoSGBM() { return Ptr_StereoSGBM(); }
operator Ptr_StereoSGBM() { return toPtrStereoSGBM(); } operator Ptr_StereoSGBM() { return toPtrStereoSGBM(); }
// --------------------------- Ptr_FeatureDetector ---------------------- // --------------------------- Ptr_FeatureDetector ----------------------
Bridge& operator=(const Ptr_FeatureDetector& obj) { return *this; } Bridge& operator=(const Ptr_FeatureDetector& ) { return *this; }
Ptr_FeatureDetector toPtrFeatureDetector() { return Ptr_FeatureDetector(); } Ptr_FeatureDetector toPtrFeatureDetector() { return Ptr_FeatureDetector(); }
operator Ptr_FeatureDetector() { return toPtrFeatureDetector(); } operator Ptr_FeatureDetector() { return toPtrFeatureDetector(); }

View File

@ -8,7 +8,6 @@
* Copyright 2013 The OpenCV Foundation * Copyright 2013 The OpenCV Foundation
*/ */
#include "mex.h" #include "mex.h"
#include "bridge.hpp"
#include <vector> #include <vector>
/* /*