From 979c834ee0f9c7bcca288040ca8011e50a160f95 Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Thu, 20 Mar 2014 14:39:01 -0400 Subject: [PATCH] Fix and add tests for empty_base_optimization. --- Builds/VisualStudio2013/beast.vcxproj | 6 + Builds/VisualStudio2013/beast.vcxproj.filters | 6 + beast/utility/Utility.cpp | 1 + beast/utility/empty_base_optimization.h | 78 +++--------- .../tests/empty_base_optimization.test.cpp | 113 ++++++++++++++++++ 5 files changed, 140 insertions(+), 64 deletions(-) create mode 100644 beast/utility/tests/empty_base_optimization.test.cpp diff --git a/Builds/VisualStudio2013/beast.vcxproj b/Builds/VisualStudio2013/beast.vcxproj index 40f4a29a1..45289b1f9 100644 --- a/Builds/VisualStudio2013/beast.vcxproj +++ b/Builds/VisualStudio2013/beast.vcxproj @@ -777,6 +777,12 @@ true true + + true + true + true + true + true diff --git a/Builds/VisualStudio2013/beast.vcxproj.filters b/Builds/VisualStudio2013/beast.vcxproj.filters index 080bb8b70..e91b7a526 100644 --- a/Builds/VisualStudio2013/beast.vcxproj.filters +++ b/Builds/VisualStudio2013/beast.vcxproj.filters @@ -321,6 +321,9 @@ {899ea9a6-1969-4cde-b26d-8ad60acebfa4} + + {3c58ba5e-1855-4865-8a9f-c0afd5014e74} + @@ -1940,6 +1943,9 @@ beast\streams + + beast\utility\tests + diff --git a/beast/utility/Utility.cpp b/beast/utility/Utility.cpp index eb5d53d3f..48175d75b 100644 --- a/beast/utility/Utility.cpp +++ b/beast/utility/Utility.cpp @@ -32,3 +32,4 @@ #include "impl/LeakChecked.cpp" #include "impl/StaticObject.cpp" #include "impl/PropertyStream.cpp" +#include "tests/empty_base_optimization.test.cpp" diff --git a/beast/utility/empty_base_optimization.h b/beast/utility/empty_base_optimization.h index 39f8d6895..fec1aebf1 100644 --- a/beast/utility/empty_base_optimization.h +++ b/beast/utility/empty_base_optimization.h @@ -24,20 +24,10 @@ #include #include -#ifndef BEAST_NO_EMPTY_BASE_OPTIMIZATION -# if defined _MSC_VER -# define BEAST_NO_EMPTY_BASE_OPTIMIZATION 1 -# else -# define BEAST_NO_EMPTY_BASE_OPTIMIZATION 1 -# endif -#endif - namespace beast { namespace detail { -#if ! BEAST_NO_EMPTY_BASE_OPTIMIZATION - template struct empty_base_optimization_decide : std::integral_constant -struct empty_base_optimization_decide - : std::false_type -{ -}; - -#endif - } //------------------------------------------------------------------------------ @@ -72,43 +52,15 @@ template < class empty_base_optimization : private T { public: - template < - class... Args, - class = typename std::enable_if < - std::is_constructible ::value>::type - > - explicit /*constexpr*/ empty_base_optimization ( - Args&&... args) - /*noexcept (std::is_nothrow_constructible ::value);*/ - : T (std::forward (args)...) - { - } + empty_base_optimization() = default; -#if 1 - empty_base_optimization (T const& t) + empty_base_optimization(T const& t) : T (t) - { - } + {} - empty_base_optimization (T&& t) + empty_base_optimization(T&& t) : T (std::move (t)) - { - } - - empty_base_optimization& operator= ( - empty_base_optimization const& other) - { - *this = other; - return *this; - } - - empty_base_optimization& operator= ( - empty_base_optimization&& other) - { - *this = std::move (other); - return *this; - } -#endif + {} T& member() noexcept { @@ -130,17 +82,15 @@ template < class empty_base_optimization { public: - template < - class... Args, - class = typename std::enable_if < - std::is_constructible ::value>::type - > - explicit /*constexpr*/ empty_base_optimization ( - Args&&... args) - /*noexcept (std::is_nothrow_constructible ::value);*/ - : m_t (std::forward (args)...) - { - } + empty_base_optimization() = default; + + empty_base_optimization(T const& t) + : m_t (t) + {} + + empty_base_optimization(T&& t) + : m_t (std::move (t)) + {} T& member() noexcept { diff --git a/beast/utility/tests/empty_base_optimization.test.cpp b/beast/utility/tests/empty_base_optimization.test.cpp new file mode 100644 index 000000000..54c967414 --- /dev/null +++ b/beast/utility/tests/empty_base_optimization.test.cpp @@ -0,0 +1,113 @@ +//-------------------- empty_base_optimization.test.cpp ------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2014 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#if BEAST_INCLUDE_BEASTCONFIG +#include "../../../BeastConfig.h" +#endif + +#include "../empty_base_optimization.h" + +#include "../../../modules/beast_core/beast_core.h" // for UnitTest + +namespace beast { + +class empty_base_optimization_Tests + : public UnitTest +{ +public: + template + class test1 + : private empty_base_optimization + { + typedef empty_base_optimization Base; + void* m_p; + public: + explicit test1 (T const& t) + : Base (t) + {} + + T& member() {return Base::member();} + T const& member() const {return Base::member();} + }; + + template + class test2 + { + void* m_p; + T m_t; + public: + explicit test2 (T const& t) + : m_t (t) + {} + + T& member() {return m_t;} + T const& member() const {return m_t;} + }; + + struct Empty + { + operator bool() {return true;} + }; + + static + bool + test_one () + { + test1 t1(1); + test2 t2(2); + static_assert(sizeof(t1) == sizeof(t2), "don't optimize for int"); + if (t1.member() != 1) + return false; + if (t2.member() != 2) + return false; + return true; + } + + static + bool + test_two () + { + test1 t1((Empty())); + test2 t2((Empty())); + static_assert(sizeof(t1) < sizeof(t2), "do optimize for Empty"); + if (t1.member() != true) + return false; + if (t2.member() != true) + return false; + return true; + } + + void + runTest () + { + beginTestCase ("empty_base_optimization"); + expect (test_one()); + expect (test_two()); + pass (); + } + + empty_base_optimization_Tests() + : UnitTest ("empty_base_optimization", "beast") + { + } +}; + +static empty_base_optimization_Tests empty_base_optimization_tests; + +} // beast