diff --git a/src/shapes/ply.cpp b/src/shapes/ply.cpp index 1c2f38fd..a6a03f7e 100644 --- a/src/shapes/ply.cpp +++ b/src/shapes/ply.cpp @@ -22,24 +22,7 @@ #include #include #include - -#if MTS_USE_BOOST_TR1 -#include -#else -#if defined(_MSC_VER) && (_MSC_VER >= 1600) #include -#else -#include -#endif -#endif - -#if !MTS_USE_BOOST_TR1 && defined(_MSC_VER) && (_MSC_VER >= 1600) -# define PLY_USE_NULLPTR 1 -#else -# define PLY_USE_NULLPTR 0 -#endif - -using namespace std::tr1::placeholders; MTS_NAMESPACE_BEGIN @@ -160,43 +143,37 @@ public: message.c_str()); } - template std::tr1::function + template std::function scalar_property_definition_callback(const std::string& element_name, const std::string& property_name); - template std::tr1::tuple, - std::tr1::function, std::tr1::function > + template std::tuple, + std::function, std::function > list_property_definition_callback(const std::string& element_name, const std::string& property_name); - std::tr1::tuple, std::tr1::function > + std::tuple, std::function > element_definition_callback(const std::string& element_name, std::size_t count) { if (element_name == "vertex") { m_vertexCount = count; m_positions = new Point[m_vertexCount]; - return std::tr1::tuple, - std::tr1::function >( - std::tr1::bind(&PLYLoader::vertex_begin_callback, this), - std::tr1::bind(&PLYLoader::vertex_end_callback, this) + return std::tuple, + std::function >( + std::bind(&PLYLoader::vertex_begin_callback, this), + std::bind(&PLYLoader::vertex_end_callback, this) ); } else if (element_name == "face") { m_faceCount = count; m_triangles = new Triangle[m_faceCount*2]; - return std::tr1::tuple, - std::tr1::function >( - std::tr1::bind(&PLYLoader::face_begin_callback, this), - std::tr1::bind(&PLYLoader::face_end_callback, this) + return std::tuple, + std::function >( + std::bind(&PLYLoader::face_begin_callback, this), + std::bind(&PLYLoader::face_end_callback, this) ); } else { -#if PLY_USE_NULLPTR return - std::tr1::tuple, - std::tr1::function >(nullptr, nullptr); -#else - return - std::tr1::tuple, - std::tr1::function >(0, 0); -#endif + std::tuple, + std::function >(nullptr, nullptr); } } @@ -325,206 +302,174 @@ private: bool m_sRGB; }; -template<> std::tr1::function +template<> std::function PLYLoader::scalar_property_definition_callback(const std::string& element_name, const std::string& property_name) { if (element_name == "vertex") { if (property_name == "x") { - return std::tr1::bind(&PLYLoader::vertex_x_callback, this, _1); + return std::bind(&PLYLoader::vertex_x_callback, this, _1); } else if (property_name == "y") { - return std::tr1::bind(&PLYLoader::vertex_y_callback, this, _1); + return std::bind(&PLYLoader::vertex_y_callback, this, _1); } else if (property_name == "z") { - return std::tr1::bind(&PLYLoader::vertex_z_callback, this, _1); + return std::bind(&PLYLoader::vertex_z_callback, this, _1); } else if (property_name == "nx") { m_hasNormals = true; - return std::tr1::bind(&PLYLoader::normal_x_callback, this, _1); + return std::bind(&PLYLoader::normal_x_callback, this, _1); } else if (property_name == "ny") { - return std::tr1::bind(&PLYLoader::normal_y_callback, this, _1); + return std::bind(&PLYLoader::normal_y_callback, this, _1); } else if (property_name == "nz") { - return std::tr1::bind(&PLYLoader::normal_z_callback, this, _1); + return std::bind(&PLYLoader::normal_z_callback, this, _1); } else if (property_name == "u" || property_name == "texture_u" || property_name == "s") { m_hasTexCoords = true; - return std::tr1::bind(&PLYLoader::texcoord_u_callback, this, _1); + return std::bind(&PLYLoader::texcoord_u_callback, this, _1); } else if (property_name == "v" || property_name == "texture_v" || property_name == "t") { - return std::tr1::bind(&PLYLoader::texcoord_v_callback, this, _1); + return std::bind(&PLYLoader::texcoord_v_callback, this, _1); } else if (property_name == "diffuse_red" || property_name == "red") { - return std::tr1::bind(&PLYLoader::red_callback, this, _1); + return std::bind(&PLYLoader::red_callback, this, _1); } else if (property_name == "diffuse_green" || property_name == "green") { - return std::tr1::bind(&PLYLoader::green_callback, this, _1); + return std::bind(&PLYLoader::green_callback, this, _1); } else if (property_name == "diffuse_blue" || property_name == "blue") { - return std::tr1::bind(&PLYLoader::blue_callback, this, _1); + return std::bind(&PLYLoader::blue_callback, this, _1); } } else if (element_name == "face") { if (property_name == "diffuse_red" || property_name == "red") { - return std::tr1::bind(&PLYLoader::face_red_callback, this, _1); + return std::bind(&PLYLoader::face_red_callback, this, _1); } else if (property_name == "diffuse_green" || property_name == "green") { - return std::tr1::bind(&PLYLoader::face_green_callback, this, _1); + return std::bind(&PLYLoader::face_green_callback, this, _1); } else if (property_name == "diffuse_blue" || property_name == "blue") { - return std::tr1::bind(&PLYLoader::face_blue_callback, this, _1); + return std::bind(&PLYLoader::face_blue_callback, this, _1); } } -#if PLY_USE_NULLPTR return nullptr; -#else - return 0; -#endif } -template<> std::tr1::function +template<> std::function PLYLoader::scalar_property_definition_callback(const std::string& element_name, const std::string& property_name) { if (element_name == "vertex") { if (property_name == "diffuse_red" || property_name == "red") { - return std::tr1::bind(&PLYLoader::red_callback_uint8, this, _1); + return std::bind(&PLYLoader::red_callback_uint8, this, _1); } else if (property_name == "diffuse_green" || property_name == "green") { - return std::tr1::bind(&PLYLoader::green_callback_uint8, this, _1); + return std::bind(&PLYLoader::green_callback_uint8, this, _1); } else if (property_name == "diffuse_blue" || property_name == "blue") { - return std::tr1::bind(&PLYLoader::blue_callback_uint8, this, _1); + return std::bind(&PLYLoader::blue_callback_uint8, this, _1); } } else if (element_name == "face") { if (property_name == "diffuse_red" || property_name == "red") { - return std::tr1::bind(&PLYLoader::face_red_callback_uint8, this, _1); + return std::bind(&PLYLoader::face_red_callback_uint8, this, _1); } else if (property_name == "diffuse_green" || property_name == "green") { - return std::tr1::bind(&PLYLoader::face_green_callback_uint8, this, _1); + return std::bind(&PLYLoader::face_green_callback_uint8, this, _1); } else if (property_name == "diffuse_blue" || property_name == "blue") { - return std::tr1::bind(&PLYLoader::face_blue_callback_uint8, this, _1); + return std::bind(&PLYLoader::face_blue_callback_uint8, this, _1); } } -#if PLY_USE_NULLPTR return nullptr; -#else - return 0; -#endif } -template<> std::tr1::tuple, - std::tr1::function, std::tr1::function > +template<> std::tuple, + std::function, std::function > PLYLoader::list_property_definition_callback(const std::string& element_name, const std::string& property_name) { if ((element_name == "face") && (property_name == "vertex_indices" || property_name == "vertex_index")) { - return std::tr1::tuple, - std::tr1::function, std::tr1::function >( - std::tr1::bind(&PLYLoader::face_vertex_indices_begin_uint8, this, _1), - std::tr1::bind(&PLYLoader::face_vertex_indices_element_int32, this, _1), - std::tr1::bind(&PLYLoader::face_vertex_indices_end, this) + return std::tuple, + std::function, std::function >( + std::bind(&PLYLoader::face_vertex_indices_begin_uint8, this, _1), + std::bind(&PLYLoader::face_vertex_indices_element_int32, this, _1), + std::bind(&PLYLoader::face_vertex_indices_end, this) ); } else { -#if PLY_USE_NULLPTR - return std::tr1::tuple, - std::tr1::function, - std::tr1::function >(nullptr, nullptr, nullptr); -#else - return std::tr1::tuple, - std::tr1::function, - std::tr1::function >(0, 0, 0); -#endif + return std::tuple, + std::function, + std::function >(nullptr, nullptr, nullptr); } } -template<> std::tr1::tuple, - std::tr1::function, std::tr1::function > +template<> std::tuple, + std::function, std::function > PLYLoader::list_property_definition_callback(const std::string& element_name, const std::string& property_name) { if ((element_name == "face") && (property_name == "vertex_indices" || property_name == "vertex_index")) { - return std::tr1::tuple, - std::tr1::function, std::tr1::function >( - std::tr1::bind(&PLYLoader::face_vertex_indices_begin_uint32, this, _1), - std::tr1::bind(&PLYLoader::face_vertex_indices_element_int32, this, _1), - std::tr1::bind(&PLYLoader::face_vertex_indices_end, this) + return std::tuple, + std::function, std::function >( + std::bind(&PLYLoader::face_vertex_indices_begin_uint32, this, _1), + std::bind(&PLYLoader::face_vertex_indices_element_int32, this, _1), + std::bind(&PLYLoader::face_vertex_indices_end, this) ); } else { -#if PLY_USE_NULLPTR - return std::tr1::tuple, - std::tr1::function, - std::tr1::function >(nullptr, nullptr, nullptr); -#else - return std::tr1::tuple, - std::tr1::function, - std::tr1::function >(0, 0, 0); -#endif + return std::tuple, + std::function, + std::function >(0, 0, 0); } } -template<> std::tr1::tuple, - std::tr1::function, std::tr1::function > +template<> std::tuple, + std::function, std::function > PLYLoader::list_property_definition_callback(const std::string& element_name, const std::string& property_name) { if ((element_name == "face") && (property_name == "vertex_indices" || property_name == "vertex_index")) { - return std::tr1::tuple, - std::tr1::function, std::tr1::function >( - std::tr1::bind(&PLYLoader::face_vertex_indices_begin_uint8, this, _1), - std::tr1::bind(&PLYLoader::face_vertex_indices_element_uint32, this, _1), - std::tr1::bind(&PLYLoader::face_vertex_indices_end, this) + return std::tuple, + std::function, std::function >( + std::bind(&PLYLoader::face_vertex_indices_begin_uint8, this, _1), + std::bind(&PLYLoader::face_vertex_indices_element_uint32, this, _1), + std::bind(&PLYLoader::face_vertex_indices_end, this) ); } else { -#if PLY_USE_NULLPTR - return std::tr1::tuple, - std::tr1::function, - std::tr1::function >(nullptr, nullptr, nullptr); -#else - return std::tr1::tuple, - std::tr1::function, - std::tr1::function >(0, 0, 0); -#endif + return std::tuple, + std::function, + std::function >(0, 0, 0); } } -template<> std::tr1::tuple, - std::tr1::function, std::tr1::function > +template<> std::tuple, + std::function, std::function > PLYLoader::list_property_definition_callback(const std::string& element_name, const std::string& property_name) { if ((element_name == "face") && (property_name == "vertex_indices" || property_name == "vertex_index")) { - return std::tr1::tuple, - std::tr1::function, std::tr1::function >( - std::tr1::bind(&PLYLoader::face_vertex_indices_begin_uint32, this, _1), - std::tr1::bind(&PLYLoader::face_vertex_indices_element_uint32, this, _1), - std::tr1::bind(&PLYLoader::face_vertex_indices_end, this) + return std::tuple, + std::function, std::function >( + std::bind(&PLYLoader::face_vertex_indices_begin_uint32, this, _1), + std::bind(&PLYLoader::face_vertex_indices_element_uint32, this, _1), + std::bind(&PLYLoader::face_vertex_indices_end, this) ); } else { -#if PLY_USE_NULLPTR - return std::tr1::tuple, - std::tr1::function, - std::tr1::function >(nullptr, nullptr, nullptr); -#else - return std::tr1::tuple, - std::tr1::function, - std::tr1::function >(0, 0, 0); -#endif + return std::tuple, + std::function, + std::function >(0, 0, 0); } } void PLYLoader::loadPLY(const fs::path &path) { ply::ply_parser ply_parser; - ply_parser.info_callback(std::tr1::bind(&PLYLoader::info_callback, - this, std::tr1::ref(m_name), _1, _2)); - ply_parser.warning_callback(std::tr1::bind(&PLYLoader::warning_callback, - this, std::tr1::ref(m_name), _1, _2)); - ply_parser.error_callback(std::tr1::bind(&PLYLoader::error_callback, - this, std::tr1::ref(m_name), _1, _2)); + ply_parser.info_callback(std::bind(&PLYLoader::info_callback, + this, std::ref(m_name), _1, _2)); + ply_parser.warning_callback(std::bind(&PLYLoader::warning_callback, + this, std::ref(m_name), _1, _2)); + ply_parser.error_callback(std::bind(&PLYLoader::error_callback, + this, std::ref(m_name), _1, _2)); - ply_parser.element_definition_callback(std::tr1::bind(&PLYLoader::element_definition_callback, + ply_parser.element_definition_callback(std::bind(&PLYLoader::element_definition_callback, this, _1, _2)); ply::ply_parser::scalar_property_definition_callbacks_type scalar_property_definition_callbacks; ply::ply_parser::list_property_definition_callbacks_type list_property_definition_callbacks; - ply::at(scalar_property_definition_callbacks) = std::tr1::bind( + ply::at(scalar_property_definition_callbacks) = std::bind( &PLYLoader::scalar_property_definition_callback, this, _1, _2); - ply::at(scalar_property_definition_callbacks) = std::tr1::bind( + ply::at(scalar_property_definition_callbacks) = std::bind( &PLYLoader::scalar_property_definition_callback, this, _1, _2); - ply::at(list_property_definition_callbacks) = std::tr1::bind( + ply::at(list_property_definition_callbacks) = std::bind( &PLYLoader::list_property_definition_callback, this, _1, _2); - ply::at(list_property_definition_callbacks) = std::tr1::bind( + ply::at(list_property_definition_callbacks) = std::bind( &PLYLoader::list_property_definition_callback, this, _1, _2); - ply::at(list_property_definition_callbacks) = std::tr1::bind( + ply::at(list_property_definition_callbacks) = std::bind( &PLYLoader::list_property_definition_callback, this, _1, _2); - ply::at(list_property_definition_callbacks) = std::tr1::bind( + ply::at(list_property_definition_callbacks) = std::bind( &PLYLoader::list_property_definition_callback, this, _1, _2); ply_parser.scalar_property_definition_callbacks(scalar_property_definition_callbacks); diff --git a/src/shapes/ply/ply_parser.cpp b/src/shapes/ply/ply_parser.cpp index 5e15eabf..6f9fb169 100644 --- a/src/shapes/ply/ply_parser.cpp +++ b/src/shapes/ply/ply_parser.cpp @@ -9,7 +9,7 @@ bool ply::ply_parser::parse(std::istream& istream) std::size_t number_of_format_statements = 0, number_of_element_statements = 0, number_of_property_statements = 0, number_of_obj_info_statements = 0, number_of_comment_statements = 0; format_type format = ascii_format; - std::vector< std::tr1::shared_ptr > elements; + std::vector< std::shared_ptr > elements; // magic char magic[3]; @@ -103,7 +103,7 @@ bool ply::ply_parser::parse(std::istream& istream) } return false; } - std::vector< std::tr1::shared_ptr >::const_iterator iterator; + std::vector< std::shared_ptr >::const_iterator iterator; for (iterator = elements.begin(); iterator != elements.end(); ++iterator) { const struct element& element = *(iterator->get()); if (element.name == name) { @@ -121,8 +121,8 @@ bool ply::ply_parser::parse(std::istream& istream) if (element_definition_callbacks_) { element_callbacks = element_definition_callbacks_(name, count); } - std::tr1::shared_ptr element_ptr(new element(name, count, std::tr1::get<0>(element_callbacks), std::tr1::get<1>(element_callbacks))); - elements.push_back(std::tr1::shared_ptr(element_ptr)); + std::shared_ptr element_ptr(new element(name, count, std::get<0>(element_callbacks), std::get<1>(element_callbacks))); + elements.push_back(std::shared_ptr(element_ptr)); current_element_ = element_ptr.get(); } @@ -154,7 +154,7 @@ bool ply::ply_parser::parse(std::istream& istream) } return false; } - std::vector< std::tr1::shared_ptr >::const_iterator iterator; + std::vector< std::shared_ptr >::const_iterator iterator; for (iterator = current_element_->properties.begin(); iterator != current_element_->properties.end(); ++iterator) { const struct property& property = *(iterator->get()); if (property.name == name) { @@ -216,7 +216,7 @@ bool ply::ply_parser::parse(std::istream& istream) } return false; } - std::vector< std::tr1::shared_ptr >::const_iterator iterator; + std::vector< std::shared_ptr >::const_iterator iterator; for (iterator = current_element_->properties.begin(); iterator != current_element_->properties.end(); ++iterator) { const struct property& property = *(iterator->get()); if (property.name == name) { @@ -392,7 +392,7 @@ bool ply::ply_parser::parse(std::istream& istream) // ascii if (format == ascii_format) { - for (std::vector< std::tr1::shared_ptr >::const_iterator element_iterator = elements.begin(); element_iterator != elements.end(); ++element_iterator) { + for (std::vector< std::shared_ptr >::const_iterator element_iterator = elements.begin(); element_iterator != elements.end(); ++element_iterator) { struct element& element = *(element_iterator->get()); for (std::size_t element_index = 0; element_index < element.count; ++element_index) { if (element.begin_element_callback) { @@ -408,7 +408,7 @@ bool ply::ply_parser::parse(std::istream& istream) std::istringstream stringstream(line); stringstream.unsetf(std::ios_base::skipws); stringstream >> std::ws; - for (std::vector< std::tr1::shared_ptr >::const_iterator property_iterator = element.properties.begin(); property_iterator != element.properties.end(); ++property_iterator) { + for (std::vector< std::shared_ptr >::const_iterator property_iterator = element.properties.begin(); property_iterator != element.properties.end(); ++property_iterator) { struct property& property = *(property_iterator->get()); if (property.parse(*this, format, stringstream) == false) { return false; @@ -437,13 +437,13 @@ bool ply::ply_parser::parse(std::istream& istream) // binary else { - for (std::vector< std::tr1::shared_ptr >::const_iterator element_iterator = elements.begin(); element_iterator != elements.end(); ++element_iterator) { + for (std::vector< std::shared_ptr >::const_iterator element_iterator = elements.begin(); element_iterator != elements.end(); ++element_iterator) { struct element& element = *(element_iterator->get()); for (std::size_t element_index = 0; element_index < element.count; ++element_index) { if (element.begin_element_callback) { element.begin_element_callback(); } - for (std::vector< std::tr1::shared_ptr >::const_iterator property_iterator = element.properties.begin(); property_iterator != element.properties.end(); ++property_iterator) { + for (std::vector< std::shared_ptr >::const_iterator property_iterator = element.properties.begin(); property_iterator != element.properties.end(); ++property_iterator) { struct property& property = *(property_iterator->get()); if (property.parse(*this, format, istream) == false) { return false; diff --git a/src/shapes/ply/ply_parser.hpp b/src/shapes/ply/ply_parser.hpp index d7f5dc9c..96713295 100644 --- a/src/shapes/ply/ply_parser.hpp +++ b/src/shapes/ply/ply_parser.hpp @@ -9,42 +9,11 @@ #include #include -#if defined(__clang__) -# define MTS_USE_BOOST_TR1 (!__has_feature(cxx_variadic_templates)) -# define ADT_WORKAROUND 1 -#else -# if defined(_MSC_VER) -# if _MSC_VER < 1600 -# define MTS_USE_BOOST_TR1 1 -# else -# define MTS_USE_BOOST_TR1 0 -# define ADT_WORKAROUND 1 -# endif -# elif defined(__INTEL_COMPILER) && !defined(__OSX__) -# define MTS_USE_BOOST_TR1 1 -# else -# define MTS_USE_BOOST_TR1 0 -# endif -#endif - -#if !defined(ADT_WORKAROUND) && (defined(__INTEL_COMPILER) || defined(__INTELLISENSE__)) #define ADT_WORKAROUND 1 -#endif -#if MTS_USE_BOOST_TR1 -#include -#include -#include -#else -#if defined(_MSC_VER) && (_MSC_VER >= 1600) #include #include #include -#else -#include -#include -#endif -#endif #include #include @@ -57,38 +26,40 @@ #include #include +using namespace std::placeholders; + namespace ply { class ply_parser { public: - typedef std::tr1::function info_callback_type; - typedef std::tr1::function warning_callback_type; - typedef std::tr1::function error_callback_type; + typedef std::function info_callback_type; + typedef std::function warning_callback_type; + typedef std::function error_callback_type; - typedef std::tr1::function magic_callback_type; - typedef std::tr1::function format_callback_type; - typedef std::tr1::function comment_callback_type; - typedef std::tr1::function obj_info_callback_type; - typedef std::tr1::function end_header_callback_type; + typedef std::function magic_callback_type; + typedef std::function format_callback_type; + typedef std::function comment_callback_type; + typedef std::function obj_info_callback_type; + typedef std::function end_header_callback_type; - typedef std::tr1::function begin_element_callback_type; - typedef std::tr1::function end_element_callback_type; - typedef std::tr1::tuple element_callbacks_type; - typedef std::tr1::function element_definition_callback_type; + typedef std::function begin_element_callback_type; + typedef std::function end_element_callback_type; + typedef std::tuple element_callbacks_type; + typedef std::function element_definition_callback_type; template struct scalar_property_callback_type { - typedef std::tr1::function type; + typedef std::function type; }; template struct scalar_property_definition_callback_type { typedef typename scalar_property_callback_type::type scalar_property_callback_type; - typedef std::tr1::function type; + typedef std::function type; }; typedef boost::mpl::vector scalar_types; @@ -138,19 +109,19 @@ public: template struct list_property_begin_callback_type { - typedef std::tr1::function type; + typedef std::function type; }; template struct list_property_element_callback_type { - typedef std::tr1::function type; + typedef std::function type; }; template struct list_property_end_callback_type { - typedef std::tr1::function type; + typedef std::function type; }; template @@ -159,8 +130,8 @@ public: typedef typename list_property_begin_callback_type::type list_property_begin_callback_type; typedef typename list_property_element_callback_type::type list_property_element_callback_type; typedef typename list_property_end_callback_type::type list_property_end_callback_type; - typedef std::tr1::function< - std::tr1::tuple< + typedef std::function< + std::tuple< list_property_begin_callback_type, list_property_element_callback_type, list_property_end_callback_type @@ -288,7 +259,7 @@ private: std::size_t count; begin_element_callback_type begin_element_callback; end_element_callback_type end_element_callback; - std::vector > properties; + std::vector > properties; }; flags_type flags_; @@ -398,7 +369,7 @@ inline void ply::ply_parser::parse_scalar_property_definition(const std::string& warning_callback_(line_number_, "property '" + std::string(type_traits::name()) + " " + property_name + "' of element '" + current_element_->name + "' is not handled"); } } - current_element_->properties.push_back(std::tr1::shared_ptr(new scalar_property(property_name, scalar_property_callback))); + current_element_->properties.push_back(std::shared_ptr(new scalar_property(property_name, scalar_property_callback))); } template @@ -414,16 +385,16 @@ inline void ply::ply_parser::parse_list_property_definition(const std::string& p typedef typename list_property_begin_callback_type::type list_property_begin_callback_type; typedef typename list_property_element_callback_type::type list_property_element_callback_type; typedef typename list_property_end_callback_type::type list_property_end_callback_type; - std::tr1::tuple list_property_callbacks; + std::tuple list_property_callbacks; if (list_property_definition_callback) { list_property_callbacks = list_property_definition_callback(current_element_->name, property_name); } - if (!std::tr1::get<0>(list_property_callbacks) || !std::tr1::get<1>(list_property_callbacks) || !std::tr1::get<2>(list_property_callbacks)) { + if (!std::get<0>(list_property_callbacks) || !std::get<1>(list_property_callbacks) || !std::get<2>(list_property_callbacks)) { if (warning_callback_) { warning_callback_(line_number_, "property 'list " + std::string(type_traits::name()) + " " + std::string(type_traits::name()) + " " + property_name + "' of element '" + current_element_->name + "' is not handled"); } } - current_element_->properties.push_back(std::tr1::shared_ptr(new list_property(property_name, std::tr1::get<0>(list_property_callbacks), std::tr1::get<1>(list_property_callbacks), std::tr1::get<2>(list_property_callbacks)))); + current_element_->properties.push_back(std::shared_ptr(new list_property(property_name, std::get<0>(list_property_callbacks), std::get<1>(list_property_callbacks), std::get<2>(list_property_callbacks)))); } template