diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index dcf97d3..83ffb5f 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -3761,6 +3761,12 @@ to be inserted in intrusive containers are allocated using `std::vector` or `std [section:release_notes Release Notes] +[section:release_notes_boost_1_58_00 Boost 1.58 Release] + +* Reduced compile-time dependencies, headers, and the use of Boost.Preprocessor, specially for hooks and iterators. + +[endsect] + [section:release_notes_boost_1_57_00 Boost 1.57 Release] * Experimental version of node checkers, contributed by Matei David. Many thanks! diff --git a/include/boost/intrusive/bstree_algorithms.hpp b/include/boost/intrusive/bstree_algorithms.hpp index de5445e..a06a886 100644 --- a/include/boost/intrusive/bstree_algorithms.hpp +++ b/include/boost/intrusive/bstree_algorithms.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -167,7 +168,7 @@ struct bstree_node_checker //! //! static void set_right(node_ptr n, node_ptr right); template -class bstree_algorithms +class bstree_algorithms : public bstree_algorithms_base { public: typedef typename NodeTraits::node node; @@ -178,7 +179,8 @@ class bstree_algorithms typedef data_for_rebalance_t data_for_rebalance; /// @cond - + typedef bstree_algorithms this_type; + typedef bstree_algorithms_base base_type; private: template struct dispose_subtree_disposer @@ -247,6 +249,7 @@ class bstree_algorithms static bool unique(const const_node_ptr & node) { return !NodeTraits::get_parent(node); } + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Requires: 'node' is a node of the tree or a header node. //! //! Effects: Returns the header of the tree. @@ -254,42 +257,8 @@ class bstree_algorithms //! Complexity: Logarithmic. //! //! Throws: Nothing. - static node_ptr get_header(const const_node_ptr & node) - { - node_ptr n(detail::uncast(node)); - node_ptr p(NodeTraits::get_parent(node)); - //If p is null, then n is the header of an empty tree - if(p){ - //Non-empty tree, check if n is neither root nor header - node_ptr pp(NodeTraits::get_parent(p)); - //If granparent is not equal to n, then n is neither root nor header, - //the try the fast path - if(n != pp){ - do{ - n = p; - p = pp; - pp = NodeTraits::get_parent(pp); - }while(n != pp); - n = p; - } - //Check if n is root or header when size() > 0 - else if(!is_header(n)){ - n = p; - } - } - return n; - /* - node_ptr h = detail::uncast(node); - node_ptr p = NodeTraits::get_parent(node); - if(p){ - while(!is_header(p)) - p = NodeTraits::get_parent(p); - return p; - } - else{ - return h; - }*/ - } + static node_ptr get_header(const const_node_ptr & node); + #endif //! Requires: node1 and node2 can't be header nodes //! of two trees. @@ -311,7 +280,7 @@ class bstree_algorithms if(node1 == node2) return; - node_ptr header1(get_header(node1)), header2(get_header(node2)); + node_ptr header1(base_type::get_header(node1)), header2(base_type::get_header(node2)); swap_nodes(node1, header1, node2, header2); } @@ -481,7 +450,7 @@ class bstree_algorithms { if(node_to_be_replaced == new_node) return; - replace_node(node_to_be_replaced, get_header(node_to_be_replaced), new_node); + replace_node(node_to_be_replaced, base_type::get_header(node_to_be_replaced), new_node); } //! Requires: node_to_be_replaced must be inserted in a tree @@ -541,6 +510,7 @@ class bstree_algorithms } } + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Requires: 'node' is a node from the tree except the header. //! //! Effects: Returns the next node of the tree. @@ -548,22 +518,7 @@ class bstree_algorithms //! Complexity: Average constant time. //! //! Throws: Nothing. - static node_ptr next_node(const node_ptr & node) - { - node_ptr const n_right(NodeTraits::get_right(node)); - if(n_right){ - return minimum(n_right); - } - else { - node_ptr n(node); - node_ptr p(NodeTraits::get_parent(n)); - while(n == NodeTraits::get_right(p)){ - n = p; - p = NodeTraits::get_parent(p); - } - return NodeTraits::get_right(n) != p ? p : n; - } - } + static node_ptr next_node(const node_ptr & node); //! Requires: 'node' is a node from the tree except the leftmost node. //! @@ -572,25 +527,7 @@ class bstree_algorithms //! Complexity: Average constant time. //! //! Throws: Nothing. - static node_ptr prev_node(const node_ptr & node) - { - if(is_header(node)){ - return NodeTraits::get_right(node); - //return maximum(NodeTraits::get_parent(node)); - } - else if(NodeTraits::get_left(node)){ - return maximum(NodeTraits::get_left(node)); - } - else { - node_ptr p(node); - node_ptr x = NodeTraits::get_parent(p); - while(p == NodeTraits::get_left(x)){ - p = x; - x = NodeTraits::get_parent(x); - } - return x; - } - } + static node_ptr prev_node(const node_ptr & node); //! Requires: 'node' is a node of a tree but not the header. //! @@ -599,15 +536,7 @@ class bstree_algorithms //! Complexity: Logarithmic to the size of the subtree. //! //! Throws: Nothing. - static node_ptr minimum(node_ptr node) - { - for(node_ptr p_left = NodeTraits::get_left(node) - ;p_left - ;p_left = NodeTraits::get_left(node)){ - node = p_left; - } - return node; - } + static node_ptr minimum(node_ptr node); //! Requires: 'node' is a node of a tree but not the header. //! @@ -616,15 +545,8 @@ class bstree_algorithms //! Complexity: Logarithmic to the size of the subtree. //! //! Throws: Nothing. - static node_ptr maximum(node_ptr node) - { - for(node_ptr p_right = NodeTraits::get_right(node) - ;p_right - ;p_right = NodeTraits::get_right(node)){ - node = p_right; - } - return node; - } + static node_ptr maximum(node_ptr node); + #endif //! Requires: 'node' must not be part of any tree. //! @@ -716,7 +638,7 @@ class bstree_algorithms if (leftmost_right){ NodeTraits::set_parent(leftmost_right, leftmost_parent); - NodeTraits::set_left(header, bstree_algorithms::minimum(leftmost_right)); + NodeTraits::set_left(header, base_type::minimum(leftmost_right)); if (is_root) NodeTraits::set_parent(header, leftmost_right); @@ -747,7 +669,7 @@ class bstree_algorithms node_ptr beg(begin_node(header)); node_ptr end(end_node(header)); std::size_t i = 0; - for(;beg != end; beg = next_node(beg)) ++i; + for(;beg != end; beg = base_type::next_node(beg)) ++i; return i; } @@ -800,6 +722,7 @@ class bstree_algorithms } } + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Requires: p is a node of a tree. //! //! Effects: Returns true if p is the header of the tree. @@ -807,22 +730,8 @@ class bstree_algorithms //! Complexity: Constant. //! //! Throws: Nothing. - static bool is_header(const const_node_ptr & p) - { - node_ptr p_left (NodeTraits::get_left(p)); - node_ptr p_right(NodeTraits::get_right(p)); - if(!NodeTraits::get_parent(p) || //Header condition when empty tree - (p_left && p_right && //Header always has leftmost and rightmost - (p_left == p_right || //Header condition when only node - (NodeTraits::get_parent(p_left) != p || - NodeTraits::get_parent(p_right) != p )) - //When tree size > 1 headers can't be leftmost's - //and rightmost's parent - )){ - return true; - } - return false; - } + static bool is_header(const const_node_ptr & p); + #endif //! Requires: "header" must be the header node of a tree. //! KeyNodePtrCompare is a function object that induces a strict weak @@ -940,7 +849,7 @@ class bstree_algorithms std::size_t n = 0; while(ret.first != ret.second){ ++n; - ret.first = next_node(ret.first); + ret.first = base_type::next_node(ret.first); } return n; } @@ -985,7 +894,7 @@ class bstree_algorithms node_ptr const lb(lower_bound(header, key, comp)); std::pair ret_ii(lb, lb); if(lb != header && !comp(key, lb)){ - ret_ii.second = next_node(ret_ii.second); + ret_ii.second = base_type::next_node(ret_ii.second); } return ret_ii; } @@ -1172,7 +1081,7 @@ class bstree_algorithms if(hint == header || comp(key, hint)){ node_ptr prev(hint); //Previous value should be less than the key - if(hint == begin_node(header) || comp((prev = prev_node(hint)), key)){ + if(hint == begin_node(header) || comp((prev = base_type::prev_node(hint)), key)){ commit_data.link_left = unique(header) || !NodeTraits::get_left(hint); commit_data.node = commit_data.link_left ? hint : prev; if(pdepth){ @@ -1422,7 +1331,7 @@ class bstree_algorithms { node_ptr x = NodeTraits::get_parent(node); if(x){ - while(!is_header(x)) + while(!base_type::is_header(x)) x = NodeTraits::get_parent(x); erase(x, node); } @@ -1543,7 +1452,7 @@ class bstree_algorithms } else{ //make y != z // y = find z's successor - y = bstree_algorithms::minimum(z_right); + y = base_type::minimum(z_right); x = NodeTraits::get_right(y); // x might be null. } @@ -1573,14 +1482,14 @@ class bstree_algorithms x_parent = y; } NodeTraits::set_parent(y, z_parent); - bstree_algorithms::set_child(header, y, z_parent, z_is_leftchild); + this_type::set_child(header, y, z_parent, z_is_leftchild); } else { // z has zero or one child, x is one child (it can be null) //Just link x to z's parent x_parent = z_parent; if(x) NodeTraits::set_parent(x, z_parent); - bstree_algorithms::set_child(header, x, z_parent, z_is_leftchild); + this_type::set_child(header, x, z_parent, z_is_leftchild); //Now update leftmost/rightmost in case z was one of them if(NodeTraits::get_left(header) == z){ @@ -1588,14 +1497,14 @@ class bstree_algorithms BOOST_ASSERT(!z_left); NodeTraits::set_left(header, !z_right ? z_parent : // makes leftmost == header if z == root - bstree_algorithms::minimum(z_right)); + base_type::minimum(z_right)); } if(NodeTraits::get_right(header) == z){ //z_right must be null because z is the rightmost BOOST_ASSERT(!z_right); NodeTraits::set_right(header, !z_left ? z_parent : // makes rightmost == header if z == root - bstree_algorithms::maximum(z_left)); + base_type::maximum(z_left)); } } @@ -1682,7 +1591,7 @@ class bstree_algorithms { node_ptr prev(pos); if(pos != NodeTraits::get_left(header)) - prev = prev_node(pos); + prev = base_type::prev_node(pos); bool link_left = unique(header) || !NodeTraits::get_left(pos); commit_data.link_left = link_left; commit_data.node = link_left ? pos : prev; @@ -1733,7 +1642,7 @@ class bstree_algorithms if(hint == header || !comp(hint, new_node)){ node_ptr prev(hint); if(hint == NodeTraits::get_left(header) || - !comp(new_node, (prev = prev_node(hint)))){ + !comp(new_node, (prev = base_type::prev_node(hint)))){ bool link_left = unique(header) || !NodeTraits::get_left(hint); commit_data.link_left = link_left; commit_data.node = link_left ? hint : prev; @@ -1945,7 +1854,7 @@ class bstree_algorithms BOOST_INTRUSIVE_INVARIANT_ASSERT((!inited(node))); node_ptr x = NodeTraits::get_parent(node); if(x){ - while(!is_header(x)){ + while(!base_type::is_header(x)){ x = NodeTraits::get_parent(x); } return x; diff --git a/include/boost/intrusive/circular_list_algorithms.hpp b/include/boost/intrusive/circular_list_algorithms.hpp index 1e888a1..9ec0770 100644 --- a/include/boost/intrusive/circular_list_algorithms.hpp +++ b/include/boost/intrusive/circular_list_algorithms.hpp @@ -211,60 +211,6 @@ class circular_list_algorithms //! Complexity: Constant //! //! Throws: Nothing. -/* - static void swap_nodes(const node_ptr &this_node, const node_ptr &other_node) - { - - if (other_node == this_node) - return; - bool empty1 = unique(this_node); - bool empty2 = unique(other_node); - - node_ptr next_this(NodeTraits::get_next(this_node)); - node_ptr prev_this(NodeTraits::get_previous(this_node)); - node_ptr next_other(NodeTraits::get_next(other_node)); - node_ptr prev_other(NodeTraits::get_previous(other_node)); - - //Do the swap - NodeTraits::set_next(this_node, next_other); - NodeTraits::set_next(other_node, next_this); - - NodeTraits::set_previous(this_node, prev_other); - NodeTraits::set_previous(other_node, prev_this); - - if (empty2){ - init(this_node); - } - else{ - NodeTraits::set_next(prev_other, this_node); - NodeTraits::set_previous(next_other, this_node); - } - if (empty1){ - init(other_node); - } - else{ - NodeTraits::set_next(prev_this, other_node); - NodeTraits::set_previous(next_this, other_node); - } - } -*/ - - //Watanabe version - private: - static void swap_prev(const node_ptr &this_node, const node_ptr &other_node) - { - node_ptr temp(NodeTraits::get_previous(this_node)); - NodeTraits::set_previous(this_node, NodeTraits::get_previous(other_node)); - NodeTraits::set_previous(other_node, temp); - } - static void swap_next(const node_ptr &this_node, const node_ptr &other_node) - { - node_ptr temp(NodeTraits::get_next(this_node)); - NodeTraits::set_next(this_node, NodeTraits::get_next(other_node)); - NodeTraits::set_next(other_node, temp); - } - - public: static void swap_nodes(const node_ptr &this_node, const node_ptr &other_node) { if (other_node == this_node) @@ -487,6 +433,21 @@ class circular_list_algorithms info.num_2nd_partition = num2; info.beg_2st_partition = new_f; } + + private: + static void swap_prev(const node_ptr &this_node, const node_ptr &other_node) + { + node_ptr temp(NodeTraits::get_previous(this_node)); + NodeTraits::set_previous(this_node, NodeTraits::get_previous(other_node)); + NodeTraits::set_previous(other_node, temp); + } + + static void swap_next(const node_ptr &this_node, const node_ptr &other_node) + { + node_ptr temp(NodeTraits::get_next(this_node)); + NodeTraits::set_next(this_node, NodeTraits::get_next(other_node)); + NodeTraits::set_next(other_node, temp); + } }; /// @cond diff --git a/include/boost/intrusive/detail/bstree_algorithms_base.hpp b/include/boost/intrusive/detail/bstree_algorithms_base.hpp new file mode 100644 index 0000000..30228aa --- /dev/null +++ b/include/boost/intrusive/detail/bstree_algorithms_base.hpp @@ -0,0 +1,180 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2014-2014 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_BSTREE_ALGORITHMS_BASE_HPP +#define BOOST_INTRUSIVE_BSTREE_ALGORITHMS_BASE_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include + +namespace boost { +namespace intrusive { + +template +class bstree_algorithms_base +{ + public: + typedef typename NodeTraits::node node; + typedef NodeTraits node_traits; + typedef typename NodeTraits::node_ptr node_ptr; + typedef typename NodeTraits::const_node_ptr const_node_ptr; + + //! Requires: 'node' is a node from the tree except the header. + //! + //! Effects: Returns the next node of the tree. + //! + //! Complexity: Average constant time. + //! + //! Throws: Nothing. + static node_ptr next_node(const node_ptr & node) + { + node_ptr const n_right(NodeTraits::get_right(node)); + if(n_right){ + return minimum(n_right); + } + else { + node_ptr n(node); + node_ptr p(NodeTraits::get_parent(n)); + while(n == NodeTraits::get_right(p)){ + n = p; + p = NodeTraits::get_parent(p); + } + return NodeTraits::get_right(n) != p ? p : n; + } + } + + //! Requires: 'node' is a node from the tree except the leftmost node. + //! + //! Effects: Returns the previous node of the tree. + //! + //! Complexity: Average constant time. + //! + //! Throws: Nothing. + static node_ptr prev_node(const node_ptr & node) + { + if(is_header(node)){ + return NodeTraits::get_right(node); + //return maximum(NodeTraits::get_parent(node)); + } + else if(NodeTraits::get_left(node)){ + return maximum(NodeTraits::get_left(node)); + } + else { + node_ptr p(node); + node_ptr x = NodeTraits::get_parent(p); + while(p == NodeTraits::get_left(x)){ + p = x; + x = NodeTraits::get_parent(x); + } + return x; + } + } + + //! Requires: 'node' is a node of a tree but not the header. + //! + //! Effects: Returns the minimum node of the subtree starting at p. + //! + //! Complexity: Logarithmic to the size of the subtree. + //! + //! Throws: Nothing. + static node_ptr minimum(node_ptr node) + { + for(node_ptr p_left = NodeTraits::get_left(node) + ;p_left + ;p_left = NodeTraits::get_left(node)){ + node = p_left; + } + return node; + } + + //! Requires: 'node' is a node of a tree but not the header. + //! + //! Effects: Returns the maximum node of the subtree starting at p. + //! + //! Complexity: Logarithmic to the size of the subtree. + //! + //! Throws: Nothing. + static node_ptr maximum(node_ptr node) + { + for(node_ptr p_right = NodeTraits::get_right(node) + ;p_right + ;p_right = NodeTraits::get_right(node)){ + node = p_right; + } + return node; + } + + //! Requires: p is a node of a tree. + //! + //! Effects: Returns true if p is the header of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + static bool is_header(const const_node_ptr & p) + { + node_ptr p_left (NodeTraits::get_left(p)); + node_ptr p_right(NodeTraits::get_right(p)); + if(!NodeTraits::get_parent(p) || //Header condition when empty tree + (p_left && p_right && //Header always has leftmost and rightmost + (p_left == p_right || //Header condition when only node + (NodeTraits::get_parent(p_left) != p || + NodeTraits::get_parent(p_right) != p )) + //When tree size > 1 headers can't be leftmost's + //and rightmost's parent + )){ + return true; + } + return false; + } + + //! Requires: 'node' is a node of the tree or a header node. + //! + //! Effects: Returns the header of the tree. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + static node_ptr get_header(const const_node_ptr & node) + { + node_ptr n(detail::uncast(node)); + node_ptr p(NodeTraits::get_parent(node)); + //If p is null, then n is the header of an empty tree + if(p){ + //Non-empty tree, check if n is neither root nor header + node_ptr pp(NodeTraits::get_parent(p)); + //If granparent is not equal to n, then n is neither root nor header, + //the try the fast path + if(n != pp){ + do{ + n = p; + p = pp; + pp = NodeTraits::get_parent(pp); + }while(n != pp); + n = p; + } + //Check if n is root or header when size() > 0 + else if(!bstree_algorithms_base::is_header(n)){ + n = p; + } + } + return n; + } +}; + +} //namespace intrusive +} //namespace boost + +#endif //BOOST_INTRUSIVE_BSTREE_ALGORITHMS_BASE_HPP diff --git a/include/boost/intrusive/detail/memory_util.hpp b/include/boost/intrusive/detail/memory_util.hpp deleted file mode 100644 index 18a5d3e..0000000 --- a/include/boost/intrusive/detail/memory_util.hpp +++ /dev/null @@ -1,92 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Pablo Halpern 2009. 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) -// -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2011-2014. 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) -// -// See http://www.boost.org/libs/intrusive for documentation. -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef BOOST_INTRUSIVE_ALLOCATOR_MEMORY_UTIL_HPP -#define BOOST_INTRUSIVE_ALLOCATOR_MEMORY_UTIL_HPP - -#if defined(_MSC_VER) -# pragma once -#endif - -#include -#include -#include -#include - -namespace boost { -namespace intrusive { -namespace detail { - -template -inline T* addressof(T& obj) -{ - return static_cast - (static_cast - (const_cast - (&reinterpret_cast(obj)) - ) - ); -} - -template -struct LowPriorityConversion -{ - // Convertible from T with user-defined-conversion rank. - LowPriorityConversion(const T&) { } -}; - -}}} //namespace boost::intrusive::detail - -#include - -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME pointer_to -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace intrusive { namespace detail { -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}} -#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, )) -#include BOOST_PP_ITERATE() - -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME static_cast_from -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace intrusive { namespace detail { -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}} -#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, )) -#include BOOST_PP_ITERATE() - -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME const_cast_from -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace intrusive { namespace detail { -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}} -#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, )) -#include BOOST_PP_ITERATE() - -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME dynamic_cast_from -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace intrusive { namespace detail { -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}} -#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, )) -#include BOOST_PP_ITERATE() - -namespace boost { -namespace intrusive { -namespace detail { - -BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(element_type) -BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(difference_type) -BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reference) -BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(value_traits_ptr) - -} //namespace detail { -} //namespace intrusive { -} //namespace boost { - -#endif // ! defined(BOOST_INTRUSIVE_ALLOCATOR_MEMORY_UTIL_HPP) diff --git a/include/boost/intrusive/detail/mpl.hpp b/include/boost/intrusive/detail/mpl.hpp index 9b2c9f1..5500389 100644 --- a/include/boost/intrusive/detail/mpl.hpp +++ b/include/boost/intrusive/detail/mpl.hpp @@ -367,6 +367,59 @@ struct TRAITS_PREFIX##_bool_is_true\ };\ // +template struct helper; + +#define BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(TRAITS_NAME, FUNC_NAME) \ + template \ + class TRAITS_NAME \ + { \ + private: \ + template \ + static yes_type check(helper*); \ + template static no_type check(...); \ + public: \ + static const bool value = sizeof(check(0)) == sizeof(yes_type); \ + }; \ +// + +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(TRAITS_NAME, FUNC_NAME) \ +template \ +struct TRAITS_NAME \ +{ \ + struct BaseMixin \ + { \ + void FUNC_NAME(); \ + }; \ + struct Base : public Type, public BaseMixin { Base(); }; \ + template class Helper{}; \ + template \ + static no_type check(U*, Helper* = 0); \ + static yes_type check(...); \ + static const bool value = sizeof(yes_type) == sizeof(check((Base*)(0))); \ +};\ +// + +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED_IGNORE_SIGNATURE(TRAITS_NAME, FUNC_NAME) \ +BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(TRAITS_NAME##_ignore_signature, FUNC_NAME) \ +\ +template \ +struct TRAITS_NAME \ + : public TRAITS_NAME##_ignore_signature \ +{};\ +// + + +template +inline T* addressof(T& obj) +{ + return static_cast + (static_cast + (const_cast + (&reinterpret_cast(obj)) + ) + ); +} + } //namespace detail } //namespace intrusive } //namespace boost diff --git a/include/boost/intrusive/detail/transform_iterator.hpp b/include/boost/intrusive/detail/transform_iterator.hpp index 698318b..dd9213d 100644 --- a/include/boost/intrusive/detail/transform_iterator.hpp +++ b/include/boost/intrusive/detail/transform_iterator.hpp @@ -90,16 +90,6 @@ class transform_iterator friend bool operator!= (const transform_iterator& i, const transform_iterator& i2) { return !(i == i2); } -/* - friend bool operator> (const transform_iterator& i, const transform_iterator& i2) - { return i2 < i; } - - friend bool operator<= (const transform_iterator& i, const transform_iterator& i2) - { return !(i > i2); } - - friend bool operator>= (const transform_iterator& i, const transform_iterator& i2) - { return !(i < i2); } -*/ friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2) { return i2.distance_to(i); } diff --git a/include/boost/intrusive/detail/tree_iterator.hpp b/include/boost/intrusive/detail/tree_iterator.hpp index 78b0fb1..1b4f6d7 100644 --- a/include/boost/intrusive/detail/tree_iterator.hpp +++ b/include/boost/intrusive/detail/tree_iterator.hpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include namespace boost { namespace intrusive { @@ -46,8 +46,9 @@ class tree_iterator typedef typename types_t::node node; typedef typename types_t::node_ptr node_ptr; typedef typename types_t::const_value_traits_ptr const_value_traits_ptr; + typedef bstree_algorithms_base node_algorithms; + static const bool stateful_value_traits = types_t::stateful_value_traits; - typedef bstree_algorithms node_algorithms; void unspecified_bool_type_func() const {} typedef void (tree_iterator::*unspecified_bool_type)() const; diff --git a/include/boost/intrusive/list.hpp b/include/boost/intrusive/list.hpp index ee31deb..4d0c0c7 100644 --- a/include/boost/intrusive/list.hpp +++ b/include/boost/intrusive/list.hpp @@ -353,7 +353,7 @@ class list_impl //! //! Complexity: Constant. const_reference front() const - { return *priv_value_traits().to_value_ptr(detail::uncast(node_traits::get_next(this->get_root_node()))); } + { return *priv_value_traits().to_value_ptr(node_traits::get_next(this->get_root_node())); } //! Effects: Returns a reference to the last element of the list. //! @@ -1248,7 +1248,7 @@ class list_impl static const_iterator s_iterator_to(const_reference value) { BOOST_STATIC_ASSERT((!stateful_value_traits)); - reference r =*pointer_traits::const_cast_from(pointer_traits::pointer_to(value)); + reference r =*detail::uncast(pointer_traits::pointer_to(value)); BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(value_traits::to_node_ptr(r))); return const_iterator(value_traits::to_node_ptr(r), const_value_traits_ptr()); } @@ -1279,7 +1279,7 @@ class list_impl //! Note: Iterators and references are not invalidated. const_iterator iterator_to(const_reference value) const { - reference r = *pointer_traits::const_cast_from(pointer_traits::pointer_to(value)); + reference r = *detail::uncast(pointer_traits::pointer_to(value)); BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(this->priv_value_traits().to_node_ptr(r))); return const_iterator(this->priv_value_traits().to_node_ptr(r), this->priv_value_traits_ptr()); } diff --git a/include/boost/intrusive/pack_options.hpp b/include/boost/intrusive/pack_options.hpp index 077b08b..fa00bea 100644 --- a/include/boost/intrusive/pack_options.hpp +++ b/include/boost/intrusive/pack_options.hpp @@ -308,7 +308,7 @@ struct pack_options //! //! \code //! struct OPTION_NAME -//! { /*unspecified_content*/ }; +//! { unspecified_content }; //! \endcode //! //! ...that after being combined with @@ -338,7 +338,7 @@ struct pack_options //! //! \code //! struct OPTION_NAME -//! { /*unspecified_content*/ }; +//! { unspecified_content }; //! \endcode //! //! ...that after being combined with diff --git a/include/boost/intrusive/pointer_traits.hpp b/include/boost/intrusive/pointer_traits.hpp index d3c66df..1d5b5e4 100644 --- a/include/boost/intrusive/pointer_traits.hpp +++ b/include/boost/intrusive/pointer_traits.hpp @@ -6,7 +6,7 @@ // ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2011-2013. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2011-2014. 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) // @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -32,6 +31,27 @@ namespace boost { namespace intrusive { +namespace detail { + +#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1310) +BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(has_member_function_callable_with_pointer_to, pointer_to); +BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(has_member_function_callable_with_dynamic_cast_from, dynamic_cast_from); +BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(has_member_function_callable_with_static_cast_from, static_cast_from); +BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(has_member_function_callable_with_const_cast_from, const_cast_from); +#else +BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED_IGNORE_SIGNATURE(has_member_function_callable_with_pointer_to, pointer_to); +BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED_IGNORE_SIGNATURE(has_member_function_callable_with_dynamic_cast_from, dynamic_cast_from); +BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED_IGNORE_SIGNATURE(has_member_function_callable_with_static_cast_from, static_cast_from); +BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED_IGNORE_SIGNATURE(has_member_function_callable_with_const_cast_from, const_cast_from); +#endif + +BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(element_type) +BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(difference_type) +BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reference) +BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(value_traits_ptr) + +} //namespace detail { + //! pointer_traits is the implementation of C++11 std::pointer_traits class with some //! extensions like castings. @@ -91,59 +111,83 @@ struct pointer_traits //! Remark: If element_type is (possibly cv-qualified) void, r type is unspecified; otherwise, //! it is element_type &. //! - //! Returns: A dereferenceable pointer to r obtained by calling Ptr::pointer_to(r). + //! Returns: A dereferenceable pointer to r obtained by calling Ptr::pointer_to(reference). //! Non-standard extension: If such function does not exist, returns pointer(addressof(r)); + //! + //! Note: For non-conforming compilers only the existence of a member function called + //! pointer_to is checked. static pointer pointer_to(reference r) { //Non-standard extension, it does not require Ptr::pointer_to. If not present //tries to converts &r to pointer. const bool value = boost::intrusive::detail:: has_member_function_callable_with_pointer_to - ::value; + ::value; boost::intrusive::detail::bool_ flag; return pointer_traits::priv_pointer_to(flag, r); } //! Remark: Non-standard extension. //! - //! Returns: A dereferenceable pointer to r obtained by calling Ptr::static_cast_from(r). + //! Returns: A dereferenceable pointer to r obtained by calling the static template function + //! Ptr::static_cast_from(UPpr/const UPpr &). //! If such function does not exist, returns pointer_to(static_cast(*uptr)) + //! + //! Note: For non-conforming compilers only the existence of a member function called + //! static_cast_from is checked. template static pointer static_cast_from(const UPtr &uptr) { + typedef const UPtr &RefArg; const bool value = boost::intrusive::detail:: has_member_function_callable_with_static_cast_from - ::value; - boost::intrusive::detail::bool_ flag; - return pointer_traits::priv_static_cast_from(flag, uptr); + ::value + || boost::intrusive::detail:: + has_member_function_callable_with_static_cast_from + ::value; + return pointer_traits::priv_static_cast_from(boost::intrusive::detail::bool_(), uptr); } //! Remark: Non-standard extension. //! - //! Returns: A dereferenceable pointer to r obtained by calling Ptr::const_cast_from(r). + //! Returns: A dereferenceable pointer to r obtained by calling the static template function + //! Ptr::const_cast_from(UPpr/const UPpr &). //! If such function does not exist, returns pointer_to(const_cast(*uptr)) + //! + //! Note: For non-conforming compilers only the existence of a member function called + //! const_cast_from is checked. template static pointer const_cast_from(const UPtr &uptr) { + typedef const UPtr &RefArg; const bool value = boost::intrusive::detail:: has_member_function_callable_with_const_cast_from - ::value; - boost::intrusive::detail::bool_ flag; - return pointer_traits::priv_const_cast_from(flag, uptr); + ::value + || boost::intrusive::detail:: + has_member_function_callable_with_const_cast_from + ::value; + return pointer_traits::priv_const_cast_from(boost::intrusive::detail::bool_(), uptr); } //! Remark: Non-standard extension. //! - //! Returns: A dereferenceable pointer to r obtained by calling Ptr::dynamic_cast_from(r). + //! Returns: A dereferenceable pointer to r obtained by calling the static template function + //! Ptr::dynamic_cast_from(UPpr/const UPpr &). //! If such function does not exist, returns pointer_to(*dynamic_cast(&*uptr)) + //! + //! Note: For non-conforming compilers only the existence of a member function called + //! dynamic_cast_from is checked. template static pointer dynamic_cast_from(const UPtr &uptr) { + typedef const UPtr &RefArg; const bool value = boost::intrusive::detail:: has_member_function_callable_with_dynamic_cast_from - ::value; - boost::intrusive::detail::bool_ flag; - return pointer_traits::priv_dynamic_cast_from(flag, uptr); + ::value + || boost::intrusive::detail:: + has_member_function_callable_with_dynamic_cast_from + ::value; + return pointer_traits::priv_dynamic_cast_from(boost::intrusive::detail::bool_(), uptr); } ///@cond diff --git a/include/boost/intrusive/sgtree.hpp b/include/boost/intrusive/sgtree.hpp index 232710e..4735f40 100644 --- a/include/boost/intrusive/sgtree.hpp +++ b/include/boost/intrusive/sgtree.hpp @@ -152,7 +152,7 @@ struct alpha_holder } h_alpha_t get_h_alpha_t() const - { return h_alpha_t(/*alpha_, */inv_minus_logalpha_); } + { return h_alpha_t(inv_minus_logalpha_); } multiply_by_alpha_t get_multiply_by_alpha_t() const { return multiply_by_alpha_t(alpha_); } diff --git a/include/boost/intrusive/slist.hpp b/include/boost/intrusive/slist.hpp index fc44cca..d8da9b9 100644 --- a/include/boost/intrusive/slist.hpp +++ b/include/boost/intrusive/slist.hpp @@ -1714,7 +1714,7 @@ class slist_impl static const_iterator s_iterator_to(const_reference value) { BOOST_STATIC_ASSERT((!stateful_value_traits)); - reference r =*pointer_traits::const_cast_from(pointer_traits::pointer_to(value)); + reference r =*detail::uncast(pointer_traits::pointer_to(value)); return const_iterator(value_traits::to_node_ptr(r), const_value_traits_ptr()); } @@ -1744,7 +1744,7 @@ class slist_impl //! Note: Iterators and references are not invalidated. const_iterator iterator_to(const_reference value) const { - reference r =*pointer_traits::const_cast_from(pointer_traits::pointer_to(value)); + reference r =*detail::uncast(pointer_traits::pointer_to(value)); BOOST_INTRUSIVE_INVARIANT_ASSERT (linear || !node_algorithms::inited(this->priv_value_traits().to_node_ptr(r))); return const_iterator(this->priv_value_traits().to_node_ptr(r), this->priv_value_traits_ptr()); } diff --git a/include/boost/intrusive/splaytree_algorithms.hpp b/include/boost/intrusive/splaytree_algorithms.hpp index c49714a..7e4c657 100644 --- a/include/boost/intrusive/splaytree_algorithms.hpp +++ b/include/boost/intrusive/splaytree_algorithms.hpp @@ -233,21 +233,21 @@ class splaytree_algorithms if(NodeTraits::get_left(z)){ splay_up(bstree_algo::prev_node(z), header); } - /* + //possibility 2 - if(NodeTraits::get_left(z)){ - node_ptr l = NodeTraits::get_left(z); - splay_up(l, header); - }*/ - /* - if(NodeTraits::get_left(z)){ - node_ptr l = bstree_algo::prev_node(z); - splay_up_impl(l, z); - }*/ - /* + //if(NodeTraits::get_left(z)){ + // node_ptr l = NodeTraits::get_left(z); + // splay_up(l, header); + //} + + //if(NodeTraits::get_left(z)){ + // node_ptr l = bstree_algo::prev_node(z); + // splay_up_impl(l, z); + //} + //possibility 4 - splay_up(z, header); - */ + //splay_up(z, header); + bstree_algo::erase(header, z); } diff --git a/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj b/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj index 5490f93..9632632 100644 --- a/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj +++ b/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj @@ -247,6 +247,9 @@ + + @@ -310,9 +313,6 @@ - - diff --git a/proj/vc7ide/pointer_traits/pointer_traits.vcproj b/proj/vc7ide/pointer_traits/pointer_traits.vcproj index 1ad31b7..d77caf9 100644 --- a/proj/vc7ide/pointer_traits/pointer_traits.vcproj +++ b/proj/vc7ide/pointer_traits/pointer_traits.vcproj @@ -30,6 +30,7 @@ DisableLanguageExtensions="FALSE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" + RuntimeTypeInfo="TRUE" UsePrecompiledHeader="0" WarningLevel="4" Detect64BitPortabilityProblems="TRUE" diff --git a/test/itestvalue.hpp b/test/itestvalue.hpp index 7935040..b9efa56 100644 --- a/test/itestvalue.hpp +++ b/test/itestvalue.hpp @@ -197,32 +197,6 @@ class pointer_holder T* const _ptr; }; -/* -struct int_testvalue_comp -{ - template - bool operator() - (const testvalue& v1, const int &i) const - { return v1.value_ < i; } - template - bool operator() - (const int &i, const testvalue& v1) const - { return i < v1.value_; } -}; - -struct int_testvalue_pcomp -{ - template - bool operator() - (const testvalue& v1, const int &i) const - { return v1.value_ < i; } - template - bool operator() - (const int &i, const testvalue& v1) const - { return i < v1.value_; } -}; -*/ - } //namespace boost{ } //namespace intrusive{ diff --git a/test/null_iterator_test.cpp b/test/null_iterator_test.cpp index 72a68f2..1905a65 100644 --- a/test/null_iterator_test.cpp +++ b/test/null_iterator_test.cpp @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include diff --git a/test/pointer_traits_test.cpp b/test/pointer_traits_test.cpp index 8c70fcb..1455e87 100644 --- a/test/pointer_traits_test.cpp +++ b/test/pointer_traits_test.cpp @@ -10,6 +10,28 @@ #include #include #include +#include + +struct CompleteSmartPtrStats +{ + static unsigned static_cast_called; + static unsigned dynamic_cast_called; + static unsigned const_cast_called; + static unsigned pointer_to_called; + + static void reset_stats() + { + static_cast_called = 0; + dynamic_cast_called = 0; + const_cast_called = 0; + pointer_to_called = 0; + } +}; + +unsigned CompleteSmartPtrStats::static_cast_called= 0; +unsigned CompleteSmartPtrStats::dynamic_cast_called = 0; +unsigned CompleteSmartPtrStats::const_cast_called = 0; +unsigned CompleteSmartPtrStats::pointer_to_called = 0; template class CompleteSmartPtr @@ -18,7 +40,6 @@ class CompleteSmartPtr friend class CompleteSmartPtr; public: - #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) template using rebind = CompleteSmartPtr; #else @@ -44,7 +65,7 @@ class CompleteSmartPtr { this->ptr_ = c.ptr_; } static CompleteSmartPtr pointer_to(T &r) - { return CompleteSmartPtr(r); } + { ++CompleteSmartPtrStats::pointer_to_called; return CompleteSmartPtr(r); } T * operator->() const { return ptr_; } @@ -54,15 +75,15 @@ class CompleteSmartPtr template static CompleteSmartPtr static_cast_from(const CompleteSmartPtr &uptr) - { return CompleteSmartPtr(*static_cast(uptr.ptr_)); } + { ++CompleteSmartPtrStats::static_cast_called; return CompleteSmartPtr(*static_cast(uptr.ptr_)); } template static CompleteSmartPtr const_cast_from(const CompleteSmartPtr &uptr) - { return CompleteSmartPtr(*const_cast(uptr.ptr_)); } + { ++CompleteSmartPtrStats::const_cast_called; return CompleteSmartPtr(*const_cast(uptr.ptr_)); } template static CompleteSmartPtr dynamic_cast_from(const CompleteSmartPtr &uptr) - { return CompleteSmartPtr(*dynamic_cast(uptr.ptr_)); } + { ++CompleteSmartPtrStats::dynamic_cast_called; return CompleteSmartPtr(*dynamic_cast(uptr.ptr_)); } friend bool operator ==(const CompleteSmartPtr &l, const CompleteSmartPtr &r) { return l.ptr_ == r.ptr_; } @@ -128,18 +149,10 @@ int main() BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same::rebind_pointer::type , double*>::value )); - if(boost::intrusive::pointer_traits::pointer_to(dummy) != &dummy){ - return 1; - } - if(boost::intrusive::pointer_traits::static_cast_from((B*)0)){ - return 1; - } - if(boost::intrusive::pointer_traits::const_cast_from((const D*)0)){ - return 1; - } - if(boost::intrusive::pointer_traits::dynamic_cast_from((B*)0)){ - return 1; - } + BOOST_TEST(boost::intrusive::pointer_traits::pointer_to(dummy) == &dummy); + BOOST_TEST(boost::intrusive::pointer_traits:: static_cast_from((B*)0) == 0); + BOOST_TEST(boost::intrusive::pointer_traits:: const_cast_from((const D*)0) == 0); + BOOST_TEST(boost::intrusive::pointer_traits:: dynamic_cast_from((B*)0) == 0); //Complete smart pointer BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same >::rebind_pointer::type , CompleteSmartPtr >::value )); - if(boost::intrusive::pointer_traits< CompleteSmartPtr > - ::pointer_to(dummy) != CompleteSmartPtr(dummy)){ - return 1; - } - if(boost::intrusive::pointer_traits< CompleteSmartPtr >:: - static_cast_from(CompleteSmartPtr()) != CompleteSmartPtr()){ - return 1; - } - if(boost::intrusive::pointer_traits< CompleteSmartPtr >:: - const_cast_from(CompleteSmartPtr()) != CompleteSmartPtr()){ - return 1; - } - if(boost::intrusive::pointer_traits< CompleteSmartPtr
>:: - dynamic_cast_from(CompleteSmartPtr()) != CompleteSmartPtr
()){ - return 1; - } + //pointer_to + CompleteSmartPtrStats::reset_stats(); + BOOST_TEST(boost::intrusive::pointer_traits< CompleteSmartPtr >::pointer_to(dummy) == CompleteSmartPtr(dummy)); + BOOST_TEST(CompleteSmartPtrStats::pointer_to_called == 1); + //static_cast_from + CompleteSmartPtrStats::reset_stats(); + BOOST_TEST(boost::intrusive::pointer_traits< CompleteSmartPtr >::static_cast_from(CompleteSmartPtr()) == CompleteSmartPtr()); + BOOST_TEST(CompleteSmartPtrStats::static_cast_called == 1); + //const_cast_from + CompleteSmartPtrStats::reset_stats(); + BOOST_TEST(boost::intrusive::pointer_traits< CompleteSmartPtr >::const_cast_from(CompleteSmartPtr()) == CompleteSmartPtr()); + BOOST_TEST(CompleteSmartPtrStats::const_cast_called == 1); + //dynamic_cast_from + CompleteSmartPtrStats::reset_stats(); + BOOST_TEST(boost::intrusive::pointer_traits< CompleteSmartPtr
>::dynamic_cast_from(CompleteSmartPtr()) == CompleteSmartPtr
()); + BOOST_TEST(CompleteSmartPtrStats::dynamic_cast_called == 1); //Simple smart pointer BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same >::rebind_pointer::type , SimpleSmartPtr >::value )); - if(boost::intrusive::pointer_traits< SimpleSmartPtr > - ::pointer_to(dummy) != SimpleSmartPtr(&dummy)){ - return 1; - } - if(boost::intrusive::pointer_traits< SimpleSmartPtr >:: - static_cast_from(SimpleSmartPtr()) != SimpleSmartPtr()){ - return 1; - } - if(boost::intrusive::pointer_traits< SimpleSmartPtr >:: - const_cast_from(SimpleSmartPtr()) != SimpleSmartPtr()){ - return 1; - } - if(boost::intrusive::pointer_traits< SimpleSmartPtr
>:: - dynamic_cast_from(SimpleSmartPtr()) != SimpleSmartPtr
()){ - return 1; - } - return 0; + + BOOST_TEST(boost::intrusive::pointer_traits< SimpleSmartPtr >::pointer_to(dummy) == SimpleSmartPtr(&dummy)); + BOOST_TEST(boost::intrusive::pointer_traits< SimpleSmartPtr > ::static_cast_from(SimpleSmartPtr()) == SimpleSmartPtr()); + BOOST_TEST(boost::intrusive::pointer_traits< SimpleSmartPtr > ::const_cast_from(SimpleSmartPtr()) == SimpleSmartPtr()); + BOOST_TEST(boost::intrusive::pointer_traits< SimpleSmartPtr
>::dynamic_cast_from(SimpleSmartPtr()) == SimpleSmartPtr
()); + + return boost::report_errors(); }