mirror of
https://github.com/boostorg/histogram.git
synced 2025-05-11 13:14:06 +00:00
Workaround for gcc bug, fix for static global variable and function in header, fix of c++20 warning
This commit is contained in:
parent
2f91f037b9
commit
0840102bfe
@ -4,12 +4,9 @@
|
|||||||
|
|
||||||
shallow_clone: true
|
shallow_clone: true
|
||||||
max_jobs: 2
|
max_jobs: 2
|
||||||
matrix:
|
|
||||||
fast_finish: true
|
|
||||||
|
|
||||||
image:
|
image:
|
||||||
- Visual Studio 2017
|
- Visual Studio 2017
|
||||||
- Ubuntu
|
|
||||||
|
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
@ -20,23 +17,17 @@ build: off
|
|||||||
|
|
||||||
environment:
|
environment:
|
||||||
B2_OPTS: -j2 -q warnings-as-errors=on
|
B2_OPTS: -j2 -q warnings-as-errors=on
|
||||||
UBSAN_OPTIONS: print_stacktrace=1
|
|
||||||
LSAN_OPTIONS: verbosity=1:log_threads=1
|
|
||||||
ASAN_OPTIONS: detect_leaks=1:detect_stack_use_after_return=1
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
# clone minimal set of Boost libraries
|
# clone minimal set of Boost libraries
|
||||||
- cd ..
|
- cd ..
|
||||||
- cmd: git clone -b %APPVEYOR_REPO_BRANCH% --depth 5 https://github.com/boostorg/boost.git
|
- git clone -b %APPVEYOR_REPO_BRANCH% --depth 5 https://github.com/boostorg/boost.git
|
||||||
- sh: git clone -b $APPVEYOR_REPO_BRANCH --depth 5 https://github.com/boostorg/boost.git
|
|
||||||
- cd boost
|
- cd boost
|
||||||
- git submodule update --init --depth 5 tools/build tools/boostdep
|
- git submodule update --init --depth 5 tools/build tools/boostdep
|
||||||
|
|
||||||
# replace Boost library with this project and install dependencies
|
# replace Boost library with this project and install dependencies
|
||||||
- cmd: xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\histogram\
|
- xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\histogram\
|
||||||
- cmd: python tools\boostdep\depinst\depinst.py -N units -N range -N accumulators --git_args "--depth 5 --jobs 2" histogram
|
- python tools\boostdep\depinst\depinst.py -N units -N range -N accumulators --git_args "--depth 5 --jobs 2" histogram
|
||||||
- sh: rm -rf libs/histogram ; mv $APPVEYOR_BUILD_FOLDER libs/histogram
|
|
||||||
- sh: python3 tools/boostdep/depinst/depinst.py --git_args "--depth 5 --jobs 2" histogram
|
|
||||||
|
|
||||||
# use hdembinski/serialization due to frequent errors in boostorg/serialization
|
# use hdembinski/serialization due to frequent errors in boostorg/serialization
|
||||||
- cd libs/serialization
|
- cd libs/serialization
|
||||||
@ -46,18 +37,11 @@ install:
|
|||||||
- cd ../..
|
- cd ../..
|
||||||
|
|
||||||
# prepare Boost build
|
# prepare Boost build
|
||||||
- cmd: cmd /c bootstrap & b2 headers & cd libs\histogram
|
- cmd /c bootstrap & b2 headers & cd libs\histogram
|
||||||
- sh: ./bootstrap.sh; ./b2 headers; cd libs/histogram
|
|
||||||
|
|
||||||
test_script:
|
test_script:
|
||||||
# on windows
|
# on windows
|
||||||
- cmd: ..\..\b2 %B2_OPTS% cxxstd=latest test//minimal test//serialization
|
- ..\..\b2 %B2_OPTS% cxxstd=latest test//minimal test//serialization
|
||||||
# on linux
|
|
||||||
- sh:
|
|
||||||
B2="../../b2 ${B2_OPTS}";
|
|
||||||
$B2 toolset=gcc-7 cxxstd=14 exception-handling=off rtti=off test//minimal &&
|
|
||||||
$B2 toolset=gcc-9 cxxstd=latest cxxflags="-O3 -funsafe-math-optimizations" examples test//all &&
|
|
||||||
$B2 toolset=clang-6 cxxstd=latest variant=histogram_ubasan test//all
|
|
||||||
|
|
||||||
## Uncomment the following to stop VM and enable interactive login.
|
## Uncomment the following to stop VM and enable interactive login.
|
||||||
## Instructions how to log into the Appveyor VM are automatically printed.
|
## Instructions how to log into the Appveyor VM are automatically printed.
|
||||||
|
66
.github/workflows/slow.yml
vendored
66
.github/workflows/slow.yml
vendored
@ -9,8 +9,14 @@ on:
|
|||||||
- 'doc/**'
|
- 'doc/**'
|
||||||
- 'tools/**'
|
- 'tools/**'
|
||||||
|
|
||||||
jobs:
|
env:
|
||||||
|
B2_OPTS: -q -j2 warnings-as-errors=on
|
||||||
|
UBSAN_OPTIONS: print_stacktrace=1
|
||||||
|
LSAN_OPTIONS: verbosity=1:log_threads=1
|
||||||
|
ASAN_OPTIONS: detect_leaks=1:detect_stack_use_after_return=1
|
||||||
|
COVERALLS_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
superproject_cmake_and_b2:
|
superproject_cmake_and_b2:
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
steps:
|
steps:
|
||||||
@ -27,15 +33,19 @@ jobs:
|
|||||||
cd ..
|
cd ..
|
||||||
cmake -DBOOST_ENABLE_CMAKE=1 -DBoost_VERBOSE=1 boost
|
cmake -DBOOST_ENABLE_CMAKE=1 -DBoost_VERBOSE=1 boost
|
||||||
ctest -j2 --output-on-failure -R boost_histogram
|
ctest -j2 --output-on-failure -R boost_histogram
|
||||||
- name: b2 cxxstd=14,17 exception-handling=on/off rtti=on/off
|
- name: prepare b2
|
||||||
run: |
|
run: |
|
||||||
cd $GITHUB_WORKSPACE/../boost
|
cd ../boost
|
||||||
./bootstrap.sh
|
./bootstrap.sh
|
||||||
./b2 headers
|
./b2 headers
|
||||||
cd libs/histogram
|
- name: b2 cxxstd=14 exception-handling=off rtti=off
|
||||||
B2="../../b2 -q -j2 warnings-as-errors=on"
|
run: |
|
||||||
$B2 cxxstd=14,17 test//all examples
|
cd ../boost/libs/histogram
|
||||||
$B2 cxxstd=14 exception-handling=off rtti=off test//minimal
|
../../b2 $B2_OPTS cxxstd=14 exception-handling=off rtti=off test//minimal
|
||||||
|
- name: b2 cxxstd=17
|
||||||
|
run: |
|
||||||
|
cd ../boost/libs/histogram
|
||||||
|
../../b2 $B2_OPTS cxxstd=17 test//all
|
||||||
|
|
||||||
cov:
|
cov:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@ -48,9 +58,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
python --version
|
python --version
|
||||||
pip install cpp-coveralls
|
pip install cpp-coveralls
|
||||||
- name: b2 toolset=gcc-8 cxxstd=latest coverage=on test//all
|
- name: prepare
|
||||||
env:
|
|
||||||
COVERALLS_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
|
|
||||||
run: |
|
run: |
|
||||||
cd ..
|
cd ..
|
||||||
git clone -b $GITHUB_BASE_REF --depth 5 https://github.com/boostorg/boost.git
|
git clone -b $GITHUB_BASE_REF --depth 5 https://github.com/boostorg/boost.git
|
||||||
@ -74,11 +82,43 @@ jobs:
|
|||||||
# simulate bundled boost by moving the headers instead of symlinking
|
# simulate bundled boost by moving the headers instead of symlinking
|
||||||
rm -rf boost/histogram.pp boost/histogram
|
rm -rf boost/histogram.pp boost/histogram
|
||||||
mv -f libs/histogram/include/boost/* boost
|
mv -f libs/histogram/include/boost/* boost
|
||||||
cd libs/histogram
|
|
||||||
|
|
||||||
B2="../../b2 -q -j2 warnings-as-errors=on"
|
- name: test gcc-8 cxxstd=latest coverage=on test//all
|
||||||
|
run: |
|
||||||
|
cd ../boost/libs/histogram
|
||||||
|
|
||||||
# don't compile examples in coverage build, coverage must come from tests alone
|
# don't compile examples in coverage build, coverage must come from tests alone
|
||||||
$B2 toolset=gcc-8 cxxstd=latest coverage=on test//all
|
../../b2 $B2_OPTS toolset=gcc-8 cxxstd=latest coverage=on test//all
|
||||||
|
|
||||||
# process and send coverage data
|
# process and send coverage data
|
||||||
GCOV=gcov-8 tools/cov.sh $COVERALLS_TOKEN
|
GCOV=gcov-8 tools/cov.sh $COVERALLS_TOKEN
|
||||||
|
|
||||||
|
stress:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: prepare b2
|
||||||
|
run: |
|
||||||
|
cd ..
|
||||||
|
git clone -b $GITHUB_BASE_REF --depth 5 https://github.com/boostorg/boost.git
|
||||||
|
cd boost
|
||||||
|
git submodule update --init --depth 5 tools/build tools/boostdep
|
||||||
|
mv -f $GITHUB_WORKSPACE/* libs/histogram
|
||||||
|
|
||||||
|
python tools/boostdep/depinst/depinst.py --git_args "--depth 5 --jobs 3" histogram
|
||||||
|
|
||||||
|
# prepare build
|
||||||
|
./bootstrap.sh
|
||||||
|
./b2 headers
|
||||||
|
- name: test gcc-7 cxxstd=14
|
||||||
|
run: |
|
||||||
|
cd ../boost/libs/histogram
|
||||||
|
../../b2 $B2_OPTS toolset=gcc-7 cxxstd=14 test//all examples
|
||||||
|
- name: test gcc-10 cxxstd=20 -O3 -funsafe-math-optimizations
|
||||||
|
run: |
|
||||||
|
cd ../boost/libs/histogram
|
||||||
|
../../b2 $B2_OPTS toolset=gcc-10 cxxstd=20 cxxflags="-O3 -funsafe-math-optimizations" test//all examples
|
||||||
|
- name: test clang-6 cxxstd=17 ubsan asan
|
||||||
|
run: |
|
||||||
|
cd ../boost/libs/histogram
|
||||||
|
../../b2 $B2_OPTS toolset=clang-6 cxxstd=17 variant=histogram_ubasan test//all
|
||||||
|
2
Jamfile
2
Jamfile
@ -17,7 +17,7 @@ project
|
|||||||
: requirements
|
: requirements
|
||||||
<implicit-dependency>/boost//headers
|
<implicit-dependency>/boost//headers
|
||||||
<include>$(BOOST_ROOT)
|
<include>$(BOOST_ROOT)
|
||||||
<toolset>clang:<cxxflags>"-pedantic -Wextra -Wsign-compare -Wstrict-aliasing -fstrict-aliasing"
|
<toolset>clang:<cxxflags>"-pedantic -Wextra -Wsign-compare -Wstrict-aliasing -fstrict-aliasing -Wvexing-parse"
|
||||||
<toolset>gcc:<cxxflags>"-pedantic -Wextra -Wsign-compare -Wstrict-aliasing -fstrict-aliasing"
|
<toolset>gcc:<cxxflags>"-pedantic -Wextra -Wsign-compare -Wstrict-aliasing -fstrict-aliasing"
|
||||||
<toolset>msvc:<cxxflags>"/bigobj"
|
<toolset>msvc:<cxxflags>"/bigobj"
|
||||||
<toolset>intel-win:<cxxflags>"/bigobj"
|
<toolset>intel-win:<cxxflags>"/bigobj"
|
||||||
|
@ -28,8 +28,6 @@ namespace boost {
|
|||||||
namespace histogram {
|
namespace histogram {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
static axis::null_type null_value;
|
|
||||||
|
|
||||||
template <class Axis>
|
template <class Axis>
|
||||||
struct value_type_deducer {
|
struct value_type_deducer {
|
||||||
using type =
|
using type =
|
||||||
@ -115,7 +113,8 @@ decltype(auto) metadata_impl(A&& a, decltype(a.metadata(), 0)) {
|
|||||||
|
|
||||||
template <class A>
|
template <class A>
|
||||||
axis::null_type& metadata_impl(A&&, float) {
|
axis::null_type& metadata_impl(A&&, float) {
|
||||||
return detail::null_value;
|
static axis::null_type null_value;
|
||||||
|
return null_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
@ -381,7 +380,7 @@ decltype(auto) value(const Axis& axis, real_index_type index) {
|
|||||||
template <class Result, class Axis>
|
template <class Result, class Axis>
|
||||||
Result value_as(const Axis& axis, real_index_type index) {
|
Result value_as(const Axis& axis, real_index_type index) {
|
||||||
return detail::try_cast<Result, std::runtime_error>(
|
return detail::try_cast<Result, std::runtime_error>(
|
||||||
value(axis, index)); // avoid conversion warning
|
axis::traits::value(axis, index)); // avoid conversion warning
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns axis index for value.
|
/** Returns axis index for value.
|
||||||
@ -407,8 +406,9 @@ axis::index_type index(const variant<Ts...>& axis, const U& value) {
|
|||||||
|
|
||||||
@param axis any axis instance
|
@param axis any axis instance
|
||||||
*/
|
*/
|
||||||
|
// gcc workaround: must use unsigned int not unsigned as return type
|
||||||
template <class Axis>
|
template <class Axis>
|
||||||
constexpr unsigned rank(const Axis& axis) {
|
constexpr unsigned int rank(const Axis& axis) {
|
||||||
(void)axis;
|
(void)axis;
|
||||||
using T = value_type<Axis>;
|
using T = value_type<Axis>;
|
||||||
// cannot use mp_eval_or since T could be a fixed-sized sequence
|
// cannot use mp_eval_or since T could be a fixed-sized sequence
|
||||||
@ -417,9 +417,11 @@ constexpr unsigned rank(const Axis& axis) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// specialization for variant
|
// specialization for variant
|
||||||
|
// gcc workaround: must use unsigned int not unsigned as return type
|
||||||
template <class... Ts>
|
template <class... Ts>
|
||||||
unsigned rank(const axis::variant<Ts...>& axis) {
|
unsigned int rank(const axis::variant<Ts...>& axis) {
|
||||||
return detail::variant_access::visit([](const auto& a) { return rank(a); }, axis);
|
return detail::variant_access::visit(
|
||||||
|
[](const auto& a) { return axis::traits::rank(a); }, axis);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns pair of axis index and shift for the value argument.
|
/** Returns pair of axis index and shift for the value argument.
|
||||||
@ -441,7 +443,7 @@ std::pair<index_type, index_type> update(Axis& axis, const U& value) noexcept(
|
|||||||
return a.update(detail::try_cast<value_type<Axis>, std::invalid_argument>(value));
|
return a.update(detail::try_cast<value_type<Axis>, std::invalid_argument>(value));
|
||||||
},
|
},
|
||||||
[&value](auto& a) -> std::pair<index_type, index_type> {
|
[&value](auto& a) -> std::pair<index_type, index_type> {
|
||||||
return {index(a, value), 0};
|
return {axis::traits::index(a, value), 0};
|
||||||
},
|
},
|
||||||
axis);
|
axis);
|
||||||
}
|
}
|
||||||
|
@ -30,9 +30,9 @@ using common_axes = mp11::mp_cond<
|
|||||||
|
|
||||||
// Non-PODs rank highest, then floats, than integers; types with more capacity are higher
|
// Non-PODs rank highest, then floats, than integers; types with more capacity are higher
|
||||||
template <class Storage>
|
template <class Storage>
|
||||||
static constexpr std::size_t type_rank() {
|
constexpr std::size_t type_rank() {
|
||||||
using T = typename Storage::value_type;
|
using T = typename Storage::value_type;
|
||||||
return !std::is_pod<T>::value * 10000 + std::is_floating_point<T>::value * 100 +
|
return !std::is_arithmetic<T>::value * 10000 + std::is_floating_point<T>::value * 100 +
|
||||||
10 * sizeof(T) + 2 * is_array_like<Storage>::value +
|
10 * sizeof(T) + 2 * is_array_like<Storage>::value +
|
||||||
is_vector_like<Storage>::value;
|
is_vector_like<Storage>::value;
|
||||||
;
|
;
|
||||||
|
@ -91,7 +91,7 @@ BOOST_HISTOGRAM_DETAIL_DETECT(is_streamable, (std::declval<std::ostream&>() << t
|
|||||||
BOOST_HISTOGRAM_DETAIL_DETECT(has_operator_preincrement, ++t);
|
BOOST_HISTOGRAM_DETAIL_DETECT(has_operator_preincrement, ++t);
|
||||||
|
|
||||||
BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_equal, (std::declval<const T&>() ==
|
BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_equal, (std::declval<const T&>() ==
|
||||||
std::declval<const U>()));
|
std::declval<const U&>()));
|
||||||
|
|
||||||
BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_radd,
|
BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_radd,
|
||||||
(std::declval<T&>() += std::declval<U>()));
|
(std::declval<T&>() += std::declval<U>()));
|
||||||
@ -106,7 +106,7 @@ BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_rdiv,
|
|||||||
(std::declval<T&>() /= std::declval<U>()));
|
(std::declval<T&>() /= std::declval<U>()));
|
||||||
|
|
||||||
BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(
|
BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(
|
||||||
has_method_eq, (std::declval<const T>().operator==(std::declval<const U>())));
|
has_method_eq, (std::declval<const T&>().operator==(std::declval<const U&>())));
|
||||||
|
|
||||||
BOOST_HISTOGRAM_DETAIL_DETECT(has_threading_support, (T::has_threading_support));
|
BOOST_HISTOGRAM_DETAIL_DETECT(has_threading_support, (T::has_threading_support));
|
||||||
|
|
||||||
|
@ -165,40 +165,63 @@ struct large_int : totally_ordered<large_int<Allocator>, large_int<Allocator>>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class U>
|
template <class U>
|
||||||
std::enable_if_t<std::is_integral<U>::value, bool> operator<(const U& o) const
|
std::enable_if_t<std::is_integral<U>::value, bool> operator<(
|
||||||
noexcept {
|
const U& o) const noexcept {
|
||||||
assert(data.size() > 0u);
|
assert(data.size() > 0u);
|
||||||
return data.size() == 1 && safe_less()(data[0], o);
|
return data.size() == 1 && safe_less()(data[0], o);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class U>
|
template <class U>
|
||||||
std::enable_if_t<std::is_integral<U>::value, bool> operator>(const U& o) const
|
std::enable_if_t<std::is_integral<U>::value, bool> operator>(
|
||||||
noexcept {
|
const U& o) const noexcept {
|
||||||
assert(data.size() > 0u);
|
assert(data.size() > 0u);
|
||||||
assert(data.size() == 1 || data.back() > 0u); // no leading zeros allowed
|
assert(data.size() == 1 || data.back() > 0u); // no leading zeros allowed
|
||||||
return data.size() > 1 || safe_less()(o, data[0]);
|
return data.size() > 1 || safe_less()(o, data[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class U>
|
template <class U>
|
||||||
std::enable_if_t<std::is_integral<U>::value, bool> operator==(const U& o) const
|
std::enable_if_t<std::is_integral<U>::value, bool> operator==(
|
||||||
noexcept {
|
const U& o) const noexcept {
|
||||||
assert(data.size() > 0u);
|
assert(data.size() > 0u);
|
||||||
return data.size() == 1 && safe_equal()(data[0], o);
|
return data.size() == 1 && safe_equal()(data[0], o);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class U>
|
template <class U>
|
||||||
std::enable_if_t<std::is_floating_point<U>::value, bool> operator<(const U& o) const
|
std::enable_if_t<std::is_floating_point<U>::value, bool> operator<(
|
||||||
noexcept {
|
const U& o) const noexcept {
|
||||||
return operator double() < o;
|
return operator double() < o;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class U>
|
template <class U>
|
||||||
std::enable_if_t<std::is_floating_point<U>::value, bool> operator>(const U& o) const
|
std::enable_if_t<std::is_floating_point<U>::value, bool> operator>(
|
||||||
noexcept {
|
const U& o) const noexcept {
|
||||||
return operator double() > o;
|
return operator double() > o;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class U>
|
template <class U>
|
||||||
std::enable_if_t<std::is_floating_point<U>::value, bool> operator==(const U& o) const
|
std::enable_if_t<std::is_floating_point<U>::value, bool> operator==(
|
||||||
noexcept {
|
const U& o) const noexcept {
|
||||||
|
return operator double() == o;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class U>
|
||||||
|
std::enable_if_t<
|
||||||
|
(!std::is_arithmetic<U>::value && std::is_convertible<U, double>::value), bool>
|
||||||
|
operator<(const U& o) const noexcept {
|
||||||
|
return operator double() < o;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class U>
|
||||||
|
std::enable_if_t<
|
||||||
|
(!std::is_arithmetic<U>::value && std::is_convertible<U, double>::value), bool>
|
||||||
|
operator>(const U& o) const noexcept {
|
||||||
|
return operator double() > o;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class U>
|
||||||
|
std::enable_if_t<
|
||||||
|
(!std::is_arithmetic<U>::value && std::is_convertible<U, double>::value), bool>
|
||||||
|
operator==(const U& o) const noexcept {
|
||||||
return operator double() == o;
|
return operator double() == o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,20 +11,25 @@
|
|||||||
#include <boost/mp11/algorithm.hpp>
|
#include <boost/mp11/algorithm.hpp>
|
||||||
#include <boost/mp11/list.hpp>
|
#include <boost/mp11/list.hpp>
|
||||||
#include <boost/mp11/utility.hpp>
|
#include <boost/mp11/utility.hpp>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace histogram {
|
namespace histogram {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
using if_not_same_and_has_eq =
|
using if_not_same = std::enable_if_t<(!std::is_same<T, U>::value), bool>;
|
||||||
std::enable_if_t<(!std::is_same<T, U>::value && has_method_eq<T, U>::value), bool>;
|
|
||||||
|
// template <class T, class U>
|
||||||
|
// using if_not_same_and_has_eq =
|
||||||
|
// std::enable_if_t<(!std::is_same<T, U>::value && !has_method_eq<T, U>::value),
|
||||||
|
// bool>;
|
||||||
|
|
||||||
// totally_ordered is for types with a <= b == !(a > b) [floats with NaN violate this]
|
// totally_ordered is for types with a <= b == !(a > b) [floats with NaN violate this]
|
||||||
// Derived must implement <,== for symmetric form and <,>,== for non-symmetric.
|
// Derived must implement <,== for symmetric form and <,>,== for non-symmetric.
|
||||||
|
|
||||||
// partially_ordered is for types with a <= b == a < b || a == b [for floats with NaN]
|
// partially_ordered is for types with a <= b == a < b || a == b [for floats with NaN]
|
||||||
// Derived must implement <,== for the symmetric form and <,>,== for non-symmetric.
|
// Derived must implement <,== for symmetric form and <,>,== for non-symmetric.
|
||||||
|
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
struct mirrored {
|
struct mirrored {
|
||||||
@ -34,32 +39,33 @@ struct mirrored {
|
|||||||
friend bool operator<=(const U& a, const T& b) noexcept { return b >= a; }
|
friend bool operator<=(const U& a, const T& b) noexcept { return b >= a; }
|
||||||
friend bool operator>=(const U& a, const T& b) noexcept { return b <= a; }
|
friend bool operator>=(const U& a, const T& b) noexcept { return b <= a; }
|
||||||
friend bool operator!=(const U& a, const T& b) noexcept { return b != a; }
|
friend bool operator!=(const U& a, const T& b) noexcept { return b != a; }
|
||||||
};
|
}; // namespace histogram
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct mirrored<T, void> {
|
struct mirrored<T, void> {
|
||||||
template <class U>
|
template <class U>
|
||||||
friend if_not_same_and_has_eq<T, U> operator<(const U& a, const T& b) noexcept {
|
friend if_not_same<T, U> operator<(const U& a, const T& b) noexcept {
|
||||||
return b > a;
|
return b > a;
|
||||||
}
|
}
|
||||||
template <class U>
|
template <class U>
|
||||||
friend if_not_same_and_has_eq<T, U> operator>(const U& a, const T& b) noexcept {
|
friend if_not_same<T, U> operator>(const U& a, const T& b) noexcept {
|
||||||
return b < a;
|
return b < a;
|
||||||
}
|
}
|
||||||
template <class U>
|
template <class U>
|
||||||
friend if_not_same_and_has_eq<T, U> operator==(const U& a, const T& b) noexcept {
|
friend std::enable_if_t<(!has_method_eq<U, T>::value), bool> operator==(
|
||||||
return b == a;
|
const U& a, const T& b) noexcept {
|
||||||
|
return b.operator==(a);
|
||||||
}
|
}
|
||||||
template <class U>
|
template <class U>
|
||||||
friend if_not_same_and_has_eq<T, U> operator<=(const U& a, const T& b) noexcept {
|
friend if_not_same<T, U> operator<=(const U& a, const T& b) noexcept {
|
||||||
return b >= a;
|
return b >= a;
|
||||||
}
|
}
|
||||||
template <class U>
|
template <class U>
|
||||||
friend if_not_same_and_has_eq<T, U> operator>=(const U& a, const T& b) noexcept {
|
friend if_not_same<T, U> operator>=(const U& a, const T& b) noexcept {
|
||||||
return b <= a;
|
return b <= a;
|
||||||
}
|
}
|
||||||
template <class U>
|
template <class U>
|
||||||
friend if_not_same_and_has_eq<T, U> operator!=(const U& a, const T& b) noexcept {
|
friend if_not_same<T, U> operator!=(const U& a, const T& b) noexcept {
|
||||||
return b != a;
|
return b != a;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -77,7 +83,7 @@ struct equality {
|
|||||||
template <class T>
|
template <class T>
|
||||||
struct equality<T, void> {
|
struct equality<T, void> {
|
||||||
template <class U>
|
template <class U>
|
||||||
friend if_not_same_and_has_eq<T, U> operator!=(const T& a, const U& b) noexcept {
|
friend if_not_same<T, U> operator!=(const T& a, const U& b) noexcept {
|
||||||
return !(a == b);
|
return !(a == b);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -91,11 +97,11 @@ struct totally_ordered_impl : equality<T, U>, mirrored<T, U> {
|
|||||||
template <class T>
|
template <class T>
|
||||||
struct totally_ordered_impl<T, void> : equality<T, void>, mirrored<T, void> {
|
struct totally_ordered_impl<T, void> : equality<T, void>, mirrored<T, void> {
|
||||||
template <class U>
|
template <class U>
|
||||||
friend if_not_same_and_has_eq<T, U> operator<=(const T& a, const U& b) noexcept {
|
friend if_not_same<T, U> operator<=(const T& a, const U& b) noexcept {
|
||||||
return !(a > b);
|
return !(a > b);
|
||||||
}
|
}
|
||||||
template <class U>
|
template <class U>
|
||||||
friend if_not_same_and_has_eq<T, U> operator>=(const T& a, const U& b) noexcept {
|
friend if_not_same<T, U> operator>=(const T& a, const U& b) noexcept {
|
||||||
return !(a < b);
|
return !(a < b);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -114,11 +120,11 @@ struct partially_ordered_impl : equality<T, U>, mirrored<T, U> {
|
|||||||
template <class T>
|
template <class T>
|
||||||
struct partially_ordered_impl<T, void> : equality<T, void>, mirrored<T, void> {
|
struct partially_ordered_impl<T, void> : equality<T, void>, mirrored<T, void> {
|
||||||
template <class U>
|
template <class U>
|
||||||
friend if_not_same_and_has_eq<T, U> operator<=(const T& a, const U& b) noexcept {
|
friend if_not_same<T, U> operator<=(const T& a, const U& b) noexcept {
|
||||||
return a < b || a == b;
|
return a < b || a == b;
|
||||||
}
|
}
|
||||||
template <class U>
|
template <class U>
|
||||||
friend if_not_same_and_has_eq<T, U> operator>=(const T& a, const U& b) noexcept {
|
friend if_not_same<T, U> operator>=(const T& a, const U& b) noexcept {
|
||||||
return a > b || a == b;
|
return a > b || a == b;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -120,3 +120,4 @@ endif()
|
|||||||
# LINK_LIBRARIES Boost::serialization)
|
# LINK_LIBRARIES Boost::serialization)
|
||||||
|
|
||||||
boost_test(TYPE run SOURCES deduction_guides_test.cpp COMPILE_FEATURES cxx_std_17)
|
boost_test(TYPE run SOURCES deduction_guides_test.cpp COMPILE_FEATURES cxx_std_17)
|
||||||
|
boost_test(TYPE run SOURCES issue_290_test.cpp COMPILE_FEATURES cxx_std_17)
|
||||||
|
@ -92,8 +92,9 @@ alias cxx14 :
|
|||||||
;
|
;
|
||||||
|
|
||||||
alias cxx17 :
|
alias cxx17 :
|
||||||
[ run deduction_guides_test.cpp ] :
|
[ run deduction_guides_test.cpp ]
|
||||||
[ requires cpp_deduction_guides ]
|
[ compile issue_290_test.cpp ]
|
||||||
|
: [ requires cpp_deduction_guides ]
|
||||||
;
|
;
|
||||||
|
|
||||||
# check that useful error messages are produced when library is used incorrectly
|
# check that useful error messages are produced when library is used incorrectly
|
||||||
|
@ -24,8 +24,6 @@ namespace tr = axis::transform;
|
|||||||
|
|
||||||
// tests requires a C++17 compatible compiler
|
// tests requires a C++17 compatible compiler
|
||||||
|
|
||||||
#define TEST BOOST_TEST_TRAIT_SAME
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
using axis::null_type;
|
using axis::null_type;
|
||||||
|
|
||||||
|
18
test/issue_290_test.cpp
Normal file
18
test/issue_290_test.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// Copyright 2020 Hans Dembinski
|
||||||
|
//
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
// - bug only appears on cxxstd=17 or higher and only in gcc
|
||||||
|
// - reported in issue: https://github.com/boostorg/histogram/issues/290
|
||||||
|
// - originally caused by rank struct in boost/type_traits/rank.hpp,
|
||||||
|
// which we emulate here to avoid the dependency on boost.type_traits
|
||||||
|
|
||||||
|
// Original: #include <boost/type_traits/rank.hpp>
|
||||||
|
template <class T>
|
||||||
|
struct rank;
|
||||||
|
|
||||||
|
#include <boost/histogram/axis/traits.hpp>
|
||||||
|
|
||||||
|
int main() { return 0; }
|
Loading…
x
Reference in New Issue
Block a user