From a91fc06bb4838dda79c133b113260611593696bb Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Thu, 6 Feb 2025 01:17:12 +0300 Subject: [PATCH] Prohibit default construction of function_output_iterator on function pointers. Default-constructed function_output_iterator with function pointers is unusable and previously would have contained an uninitialized function pointer. Disable the default constructor using SFINAE to prevent misuse. Also reformat code. --- .../iterator/function_output_iterator.hpp | 91 ++++++++++--------- test/Jamfile.v2 | 1 + test/function_output_iterator_def_ctor_cf.cpp | 14 +++ 3 files changed, 64 insertions(+), 42 deletions(-) create mode 100644 test/function_output_iterator_def_ctor_cf.cpp diff --git a/include/boost/iterator/function_output_iterator.hpp b/include/boost/iterator/function_output_iterator.hpp index d562475..8913e93 100644 --- a/include/boost/iterator/function_output_iterator.hpp +++ b/include/boost/iterator/function_output_iterator.hpp @@ -8,69 +8,76 @@ // 27 Feb 2001 Jeremy Siek // Initial checkin. -#ifndef BOOST_ITERATOR_FUNCTION_OUTPUT_ITERATOR_HPP -#define BOOST_ITERATOR_FUNCTION_OUTPUT_ITERATOR_HPP +#ifndef BOOST_ITERATOR_FUNCTION_OUTPUT_ITERATOR_HPP_INCLUDED_ +#define BOOST_ITERATOR_FUNCTION_OUTPUT_ITERATOR_HPP_INCLUDED_ #include #include #include -#include - namespace boost { namespace iterators { - template - class function_output_iterator { - private: - typedef function_output_iterator self; - - class output_proxy { +template< typename UnaryFunction > +class function_output_iterator +{ +private: + class output_proxy + { public: - explicit output_proxy(UnaryFunction& f) BOOST_NOEXCEPT : m_f(f) { } + explicit output_proxy(UnaryFunction& f) noexcept : + m_f(f) + {} - template + template< typename T > + typename std::enable_if< + !std::is_same< typename std::remove_cv< typename std::remove_reference< T >::type >::type, output_proxy >::value, + output_proxy const& + >::type operator=(T&& value) const + { + m_f(static_cast< T&& >(value)); + return *this; + } - typename std::enable_if< - !std::is_same< typename std::remove_cv< typename std::remove_reference< T >::type >::type, output_proxy >::value, - output_proxy const& - >::type operator=(T&& value) const { - m_f(static_cast< T&& >(value)); - return *this; - } - - BOOST_DEFAULTED_FUNCTION(output_proxy(output_proxy const& that), BOOST_NOEXCEPT : m_f(that.m_f) {}) - BOOST_DELETED_FUNCTION(output_proxy& operator=(output_proxy const&)) + output_proxy(output_proxy const& that) = default; + output_proxy& operator=(output_proxy const&) = delete; private: - UnaryFunction& m_f; + UnaryFunction& m_f; }; - public: - typedef std::output_iterator_tag iterator_category; - typedef void value_type; - typedef std::ptrdiff_t difference_type; - typedef void pointer; - typedef void reference; +public: + using iterator_category = std::output_iterator_tag; + using value_type = void; + using difference_type = std::ptrdiff_t; + using pointer = void; + using reference = void; - explicit function_output_iterator() {} + template< + bool Requires = std::is_class< UnaryFunction >::value, + typename = typename std::enable_if< Requires >::type + > + function_output_iterator() : + m_f() + {} - explicit function_output_iterator(const UnaryFunction& f) - : m_f(f) {} + explicit function_output_iterator(UnaryFunction const& f) : + m_f(f) + {} output_proxy operator*() { return output_proxy(m_f); } - self& operator++() { return *this; } - self& operator++(int) { return *this; } + function_output_iterator& operator++() { return *this; } + function_output_iterator& operator++(int) { return *this; } - private: +private: UnaryFunction m_f; - }; +}; - template - inline function_output_iterator - make_function_output_iterator(const UnaryFunction& f = UnaryFunction()) { - return function_output_iterator(f); - } +template< typename UnaryFunction > +inline function_output_iterator< UnaryFunction > make_function_output_iterator(UnaryFunction const& f = UnaryFunction()) +{ + return function_output_iterator< UnaryFunction >(f); +} } // namespace iterators @@ -79,4 +86,4 @@ using iterators::make_function_output_iterator; } // namespace boost -#endif // BOOST_ITERATOR_FUNCTION_OUTPUT_ITERATOR_HPP +#endif // BOOST_ITERATOR_FUNCTION_OUTPUT_ITERATOR_HPP_INCLUDED_ diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 5d8330f..d89fb37 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -58,6 +58,7 @@ test-suite iterator [ run function_input_iterator_test.cpp ] [ run function_output_iterator_test.cpp ] [ compile-fail function_output_iterator_cf.cpp ] + [ compile-fail function_output_iterator_def_ctor_cf.cpp ] [ run generator_iterator_test.cpp ] diff --git a/test/function_output_iterator_def_ctor_cf.cpp b/test/function_output_iterator_def_ctor_cf.cpp new file mode 100644 index 0000000..d023aeb --- /dev/null +++ b/test/function_output_iterator_def_ctor_cf.cpp @@ -0,0 +1,14 @@ +// Copyright 2025 (c) Andrey Semashev +// Distributed under the Boost Software License Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +int main() +{ + boost::iterators::function_output_iterator< void (*)(int) > it; + (void)it; + + return 0; +}