diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..4ea774d --- /dev/null +++ b/.travis.yml @@ -0,0 +1,47 @@ +# Copyright (C) 2016 Daniel James. +# 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) + +# Use Trusty to get a reasonably recent version of Boost. +sudo: required +dist: trusty + +language: c++ + +addons: + apt: + packages: + - libboost-dev + - libboost-tools-dev + +matrix: + include: + - compiler: gcc + env: BJAM_TOOLSET=gcc + - compiler: gcc + env: BJAM_TOOLSET=gcc-std11 + - compiler: clang + env: BJAM_TOOLSET=clang + - compiler: clang + env: BJAM_TOOLSET=clang-std11 + +before_script: + - | + echo "using gcc : : g++-4.8 ;" > ~/user-config.jam + echo "using gcc : std11 : g++-4.8 --std=c++11 ;" >> ~/user-config.jam + echo "using clang : : clang++ ;" >> ~/user-config.jam + echo "using clang : std11 : clang++ --std=c++11 ;" >> ~/user-config.jam + - cat ~/user-config.jam + - touch Jamroot.jam + +script: + - cd ${TRAVIS_BUILD_DIR}/test + - bjam -q ${BJAM_TOOLSET} include=${TRAVIS_BUILD_DIR}/include + - cd ${TRAVIS_BUILD_DIR}/hash/test + - bjam -q ${BJAM_TOOLSET} include=${TRAVIS_BUILD_DIR}/include + - cd ${TRAVIS_BUILD_DIR}/forward/test + - bjam -q ${BJAM_TOOLSET} include=${TRAVIS_BUILD_DIR}/include + - cd ${TRAVIS_BUILD_DIR}/factory/test + - bjam -q ${BJAM_TOOLSET} include=${TRAVIS_BUILD_DIR}/include + - cd ${TRAVIS_BUILD_DIR}/overloaded_function/test + - bjam -q ${BJAM_TOOLSET} include=${TRAVIS_BUILD_DIR}/include diff --git a/forward/test/forward_adapter.cpp b/forward/test/forward_adapter.cpp index 2317ce7..09cef7e 100644 --- a/forward/test/forward_adapter.cpp +++ b/forward/test/forward_adapter.cpp @@ -44,6 +44,10 @@ public: { return -(l=r+val); } + char operator()(int& l, int& r) + { + return l=r+val; + } template struct result @@ -89,8 +93,11 @@ int main() // lvalue,lvalue BOOST_TEST(( is_same< result_of< f(int&, int&) >::type, char >::value )); + // result_of works differently for C++11 here, so compare + // with using it against test_func. BOOST_TEST(( is_same< - result_of< f const (int&, int&) >::type, char >::value )); + result_of< f const (int&, int&) >::type, + result_of< test_func<> const (int&, int&)>::type >::value )); } { diff --git a/forward/test/lightweight_forward_adapter.cpp b/forward/test/lightweight_forward_adapter.cpp index 7b0d304..dbd0f3f 100644 --- a/forward/test/lightweight_forward_adapter.cpp +++ b/forward/test/lightweight_forward_adapter.cpp @@ -44,6 +44,10 @@ public: { return -(l=r+val); } + char operator()(int & l, int & r) + { + return l=r+val; + } template struct result @@ -91,8 +95,11 @@ int main() // lvalue,lvalue BOOST_TEST(( is_same< result_of< f(ref, ref) >::type, char >::value )); + // result_of works differently for C++11 here, so compare + // with using it against test_func. BOOST_TEST(( is_same< - result_of< f const (ref, ref) >::type, char >::value )); + result_of< f const (ref, ref) >::type, + result_of< test_func<> const (int&, int&) >::type >::value )); } { using boost::noncopyable; diff --git a/hash/examples/point.cpp b/hash/examples/point.cpp index 6943342..f3d30e1 100644 --- a/hash/examples/point.cpp +++ b/hash/examples/point.cpp @@ -3,6 +3,11 @@ // 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) +// Force use of assert. +#if defined(NDEBUG) +#undef NDEBUG +#endif + #include #include diff --git a/hash/examples/portable.cpp b/hash/examples/portable.cpp index 88f2fc7..511133e 100644 --- a/hash/examples/portable.cpp +++ b/hash/examples/portable.cpp @@ -3,6 +3,11 @@ // 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) +// Force use of assert. +#if defined(NDEBUG) +#undef NDEBUG +#endif + #include #include diff --git a/hash/test/hash_number_test.cpp b/hash/test/hash_number_test.cpp index 242c731..9adb5c6 100644 --- a/hash/test/hash_number_test.cpp +++ b/hash/test/hash_number_test.cpp @@ -58,8 +58,6 @@ void numeric_extra_tests(typename template void numeric_test(T*) { - typedef boost::hash_detail::limits limits; - compile_time_tests((T*) 0); BOOST_HASH_TEST_NAMESPACE::hash x1; diff --git a/hash/test/hash_string_test.cpp b/hash/test/hash_string_test.cpp index de8ca87..5f72d4e 100644 --- a/hash/test/hash_string_test.cpp +++ b/hash/test/hash_string_test.cpp @@ -38,6 +38,23 @@ void string_tests() #endif } +void string0_tests() +{ + std::string x1(1, '\0'); + std::string x2(2, '\0'); + std::string x3(3, '\0'); + std::string x4(10, '\0'); + + BOOST_HASH_TEST_NAMESPACE::hash hasher; + + BOOST_TEST(hasher(x1) != hasher(x2)); + BOOST_TEST(hasher(x1) != hasher(x3)); + BOOST_TEST(hasher(x1) != hasher(x4)); + BOOST_TEST(hasher(x2) != hasher(x3)); + BOOST_TEST(hasher(x2) != hasher(x4)); + BOOST_TEST(hasher(x3) != hasher(x4)); +} + #if !defined(BOOST_NO_STD_WSTRING) void wstring_tests() { @@ -66,6 +83,7 @@ void wstring_tests() int main() { string_tests(); + string0_tests(); #if !defined(BOOST_NO_STD_WSTRING) wstring_tests(); #endif diff --git a/include/boost/functional/forward_adapter.hpp b/include/boost/functional/forward_adapter.hpp index 796abd2..6023fc2 100644 --- a/include/boost/functional/forward_adapter.hpp +++ b/include/boost/functional/forward_adapter.hpp @@ -144,8 +144,30 @@ namespace boost : boost::result_of< BOOST_DEDUCED_TYPENAME c::t() > { }; - template< class MD, class F, class FC > - struct forward_adapter_impl + // WHen operator()() doesn't have any parameters, it can't + // be templatized and can't use SFINAE, so intead use class + // template parameter SFINAE to decide whether to instantiate it. + + template + struct forward_adapter_sfinae + { + typedef T type; + }; + + // This is the fallback for when there isn't an operator()(), + // need to create an operator() that will never instantiate + // so that using parent::operator() will work okay. + template< class MD, class F, class FC, class Enable = void> + struct forward_adapter_impl_zero + { + template struct never_instantiate {}; + template + typename never_instantiate::type operator()(T) const {} + }; + + template< class MD, class F, class FC> + struct forward_adapter_impl_zero::type>::type> { inline typename boost::result_of< FC() >::type operator()() const @@ -158,6 +180,13 @@ namespace boost { return static_cast(this)->target_function()(); } + }; + + template< class MD, class F, class FC > + struct forward_adapter_impl + : forward_adapter_impl_zero + { + using forward_adapter_impl_zero::operator(); // closing brace gets generated by preprocessing code, below diff --git a/include/boost/functional/hash/hash.hpp b/include/boost/functional/hash/hash.hpp index 2fb9f21..0a8ceeb 100644 --- a/include/boost/functional/hash/hash.hpp +++ b/include/boost/functional/hash/hash.hpp @@ -212,7 +212,6 @@ namespace boost seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2); } - template inline void hash_combine_impl(boost::uint32_t& h1, boost::uint32_t k1) { @@ -229,12 +228,11 @@ namespace boost } -// Don't define 64-bit hash combine on platforms with 64 bit integers, +// Don't define 64-bit hash combine on platforms without 64 bit integers, // and also not for 32-bit gcc as it warns about the 64-bit constant. #if !defined(BOOST_NO_INT64_T) && \ !(defined(__GNUC__) && ULONG_MAX == 0xffffffff) - template inline void hash_combine_impl(boost::uint64_t& h, boost::uint64_t k) { @@ -247,6 +245,10 @@ namespace boost h ^= k; h *= m; + + // Completely arbitrary number, to prevent 0's + // from hashing to 0. + h += 0xe6546b64; } #endif // BOOST_NO_INT64_T diff --git a/include/boost/functional/lightweight_forward_adapter.hpp b/include/boost/functional/lightweight_forward_adapter.hpp index 637aa9e..2706d29 100644 --- a/include/boost/functional/lightweight_forward_adapter.hpp +++ b/include/boost/functional/lightweight_forward_adapter.hpp @@ -149,8 +149,31 @@ namespace boost : boost::result_of< BOOST_DEDUCED_TYPENAME c::t() > { }; - template< class MD, class F, class FC > - struct lightweight_forward_adapter_impl + // When operator() doesn't have any parameters, it can't + // be templatized and can't use SFINAE, so intead use class + // template parameter SFINAE to decide whether to instantiate it. + + template + struct lightweight_forward_adapter_sfinae + { + typedef T type; + }; + + // This is the fallback for when there isn't an operator()(), + // need to create an operator() that will never instantiate + // so that using parent::operator() will work okay. + template< class MD, class F, class FC, class Enable = void> + struct lightweight_forward_adapter_impl_zero + : lightweight_forward_adapter_result + { + template struct never_instantiate {}; + template + typename never_instantiate::type operator()(T) const {} + }; + + template< class MD, class F, class FC> + struct lightweight_forward_adapter_impl_zero::type>::type> : lightweight_forward_adapter_result { inline typename boost::result_of< FC() >::type @@ -166,6 +189,12 @@ namespace boost } }; + template< class MD, class F, class FC > + struct lightweight_forward_adapter_impl + : lightweight_forward_adapter_impl_zero + { + }; + # define BOOST_PP_FILENAME_1 \ # define BOOST_PP_ITERATION_LIMITS \