Skip to content

Commit

Permalink
Fixing transform for C++20 (#125)
Browse files Browse the repository at this point in the history
* fixing transform

- Fixed transform for C++20, deprecated older names, and updated sources
- Add cmake preset for C++20
- Cleaned up docs in functional.hpp

* Use of deprecated type in deprecated function generated warning on Visual Studio.

* Added noexcept propogation

Added noexcept propagation
Added unit test

* Adding parentheses to improve formatting

Cleaned out unused properties in build matrix.

* Adding static casts for Visual C++
  • Loading branch information
sean-parent authored Oct 30, 2024
1 parent fcd6fb1 commit d9f4321
Show file tree
Hide file tree
Showing 11 changed files with 172 additions and 65 deletions.
2 changes: 0 additions & 2 deletions .github/matrix.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@
},
{
"name": "Windows VS2022",
"compiler": "Visual Studio",
"version": "17.4",
"os": "windows-2022",
"cxxstd" : "17"
}
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/adobe_source_libraries.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ on:
- main

jobs:
# Information on the runner matrix can be found in the `matrix.json` file. To find available
# versions of compilers, check https://github.com/actions/runner-images/.
generate-matrix:
name: Generate job matrix
runs-on: ubuntu-22.04
Expand Down
4 changes: 2 additions & 2 deletions .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
"macFrameworkPath": [
"/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks"
],
"compilerPath": "/usr/bin/clang",
"compilerPath": "/usr/bin/clang++",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "macos-clang-arm64",
"compileCommands": "${workspaceFolder}/build/compile_commands.json"
}
],
"version": 4
}
}
7 changes: 5 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"files.associations": {
"*.cpp": "cpp",
"__bit_reference": "cpp",
"__bits": "cpp",
"__config": "cpp",
Expand Down Expand Up @@ -128,6 +129,8 @@
"*.ipp": "cpp",
"*.tcc": "cpp",
"rope": "cpp",
"slist": "cpp"
}
"slist": "cpp",
"print": "cpp"
},
"C_Cpp.default.compilerPath": "/usr/bin/clang++"
}
22 changes: 20 additions & 2 deletions CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,31 @@
}
},
{
"name": "macos-debug",
"displayName": "macos-debug",
"name": "macos-debug-C++20",
"displayName": "macos-debug-C++20",
"description": "Sets Ninja generator, build and install directory",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_CXX_STANDARD": "20",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}"
},
"vendor": {
"microsoft.com/VisualStudioSettings/CMake/1.0": {
"hostOS": [ "macOS" ]
}
}
},
{
"name": "macos-debug-C++17",
"displayName": "macos-debug-C++17",
"description": "Sets Ninja generator, build and install directory",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_CXX_STANDARD": "17",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}"
},
"vendor": {
Expand Down
2 changes: 1 addition & 1 deletion adobe/algorithm/reduce.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ reduce_balanced(I f, I l, Op op, ADOBE_VALUE_TYPE(I) z = adobe::identity_element
++f;
}

return reduce_nonzeros(v.begin(), v.end(), f_transpose(op), z);
return reduce_nonzeros(v.begin(), v.end(), transpose(op), z);
}

/**************************************************************************************************/
Expand Down
98 changes: 42 additions & 56 deletions adobe/functional.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
#include <adobe/config.hpp>

#include <functional>
#include <utility>
#include <tuple>
#include <type_traits>
#include <utility>

#include <boost/compressed_pair.hpp>

Expand Down Expand Up @@ -124,42 +125,6 @@ pointed to by \c member.
An adobe::mem_data_t function object.
*/

/*!
\class adobe::indirect_t
\ingroup misc_functional
\brief Adapter used to convert pointers to references.
*/

/*!
\defgroup bitwise_operators Bitwise Operations
\ingroup adobe_functional
The library provides basic function object classes for all of the bitwise logical operators in the
language.
*/

/*!
\class adobe::bitwise_or
\ingroup bitwise_operators
\brief \c operator() returns <code>x | y</code>.
*/

/*!
\class adobe::bitwise_and
\ingroup bitwise_operators
\brief \c operator() returns <code>x & y</code>.
*/

/*!
\class adobe::bitwise_xor
\ingroup bitwise_operators
\brief \c operator() returns <code>x ^ y</code>.
*/


/*! \addtogroup misc_functional
@{
Expand Down Expand Up @@ -301,7 +266,7 @@ struct sequence_t

template <class T, typename R, class Compare>
struct compare_members_t {
compare_members_t(R T::*member, Compare compare) : compare_m(compare), member_m(member) {}
compare_members_t(R T::* member, Compare compare) : compare_m(compare), member_m(member) {}

bool operator()(const T& x, const T& y) const { return compare_m(x.*member_m, y.*member_m); }

Expand All @@ -315,16 +280,16 @@ struct compare_members_t {
*/

Compare compare_m;
R T::*member_m;
R T::* member_m;
};

template <class T, typename R>
compare_members_t<T, R, std::less<R>> compare_members(R T::*member) {
compare_members_t<T, R, std::less<R>> compare_members(R T::* member) {
return compare_members_t<T, R, std::less<R>>(member, std::less<R>());
}

template <class T, typename R, class Compare>
compare_members_t<T, R, Compare> compare_members(R T::*member, Compare compare) {
compare_members_t<T, R, Compare> compare_members(R T::* member, Compare compare) {
return compare_members_t<T, R, Compare>(member, compare);
}

Expand All @@ -334,28 +299,28 @@ template <class T, typename R>
struct mem_data_t {
mem_data_t() {}

explicit mem_data_t(R T::*member) : member_m(member) {}
explicit mem_data_t(R T::* member) : member_m(member) {}

R& operator()(T& x) const { return x.*member_m; }

const R& operator()(const T& x) const { return x.*member_m; }

private:
R T::*member_m;
R T::* member_m;
};

template <class T, typename R>
struct mem_data_t<const T, R> {
explicit mem_data_t(R T::*member) : member_m(member) {}
explicit mem_data_t(R T::* member) : member_m(member) {}

const R& operator()(const T& x) const { return x.*member_m; }

private:
R T::*member_m;
R T::* member_m;
};

template <class T, typename R>
mem_data_t<T, R> mem_data(R T::*member) {
mem_data_t<T, R> mem_data(R T::* member) {
return mem_data_t<T, R>(member);
}

Expand All @@ -377,24 +342,45 @@ struct equivalent {

/**************************************************************************************************/

/// A function object that transposes the arguments of a binary function. The call qualifiers are
/// preserved.
template <class F> // F models a BinaryFunction
struct transposer {
typedef typename F::second_argument_type first_argument_type;
typedef typename F::first_argument_type second_argument_type;
typedef typename F::result_type result_type;
struct transpose {
F function;

F fun;
transpose() = default;
explicit transpose(F&& f) noexcept : function(std::move(f)) {}
explicit transpose(const F& f) : function(f) {}

transposer(const F& f) : fun(f) {}
transpose(const transpose& x) = default;
transpose(transpose&& x) noexcept = default;

result_type operator()(const first_argument_type& x, const second_argument_type& y) const {
return fun(y, x);
transpose& operator=(const transpose& x) = default;
transpose& operator=(transpose&& x) noexcept = default;

template <class T1, class T2>
auto operator()(T1&& x, T2&& y) const& noexcept(std::is_nothrow_invocable_v<const F&, T2, T1>) {
return function(std::forward<T2>(y), std::forward<T1>(x));
}

template <class T1, class T2>
auto operator()(T1&& x, T2&& y) & noexcept(std::is_nothrow_invocable_v<F&, T2, T1>) {
return function(std::forward<T2>(y), std::forward<T1>(x));
}

template <class T1, class T2>
auto operator()(T1&& x, T2&& y) && noexcept(std::is_nothrow_invocable_v<F&&, T2, T1>) {
return std::move(function)(std::forward<T2>(y), std::forward<T1>(x));
}
};

template <class F> // F models a BinaryFunction
using transposer [[deprecated("Use `adobe::transpose` instead.")]] = transpose<F>;


template <typename F> // F models BinaryFunction
inline transposer<F> f_transpose(F f) {
return transposer<F>(f);
inline auto f_transpose [[deprecated("Use `adobe::transpose` instead.")]] (F f) -> transpose<F> {
return transpose<F>(f);
}

//!@}
Expand Down
1 change: 1 addition & 0 deletions test/unit_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ add_subdirectory(enum_ops)
add_subdirectory(equal_range)
add_subdirectory(erase)
add_subdirectory(forest)
add_subdirectory(functional)
add_subdirectory(lower_bound)
add_subdirectory(name)
1 change: 1 addition & 0 deletions test/unit_tests/functional/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
asl_test(BOOST NAME functional_transpose SOURCES functional_test.cpp)
93 changes: 93 additions & 0 deletions test/unit_tests/functional/functional_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
Copyright 2013 Adobe
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 <adobe/functional.hpp> // file be tested included first

#include <utility>

#include <adobe/enum_ops.hpp>

#define BOOST_TEST_MAIN

// boost
#include <boost/test/unit_test.hpp>

/**************************************************************************************************/

using namespace std;
using namespace adobe;

namespace {

/// An enumeration of member function qualifiers as bit fields to identify or mask an overload.
enum member_function_qualifiers {
_none = 0,
_const_lvalue = 1 << 0,
_lvalue = 1 << 1,
_rvalue = 1 << 2,
_all = _const_lvalue | _lvalue | _rvalue
};

auto adobe_enable_bitmask_enum(member_function_qualifiers) -> std::true_type;

/// An overload of a binary function that returns a tuple of its arguments and the qualifiers used.
/// Only the members specified by the noexcept_qualifier mask are noexcept.
template <member_function_qualifiers noexcept_qualifier>
struct test_binary_function {
auto operator()(int x, int y) const& noexcept((noexcept_qualifier & _const_lvalue) != _none) {
return tuple(x, y, _const_lvalue);
}
auto operator()(int x, int y) & noexcept((noexcept_qualifier & _lvalue) != _none) {
return tuple(x, y, _lvalue);
}
auto operator()(int x, int y) && noexcept((noexcept_qualifier & _rvalue) != _none) {
return tuple(x, y, _rvalue);
}
};

} // namespace

/*
REVISIT(sean-parent) : The static casts are necessary to get this code to compile on VC++14.
It is unclear why the compiler is unable to find the enum operators.
*/


BOOST_AUTO_TEST_CASE(functional_transpose) {

// Test that the transpose functional object correctly transposes the arguments of a binary
// function. It also tests that the correct overload is selected and that the noexcept
// qualifier is correctly propagated.

transpose lvalue{
test_binary_function<static_cast<member_function_qualifiers>(_all ^ _lvalue)>{}};
const transpose const_lvalue{
test_binary_function<static_cast<member_function_qualifiers>(_all ^ _const_lvalue)>{}};
transpose lvalue_noexcept{test_binary_function<_lvalue>{}};
const transpose const_lvalue_noexcept{test_binary_function<_const_lvalue>{}};

BOOST_TEST((lvalue(1, 2) == tuple(2, 1, _lvalue)));
BOOST_TEST(!noexcept(lvalue(1, 2)));

BOOST_TEST((const_lvalue(1, 2) == tuple(2, 1, _const_lvalue)));
BOOST_TEST(!noexcept(const_lvalue(1, 2)));

BOOST_TEST((lvalue_noexcept(1, 2) == tuple(2, 1, _lvalue)));
BOOST_TEST(noexcept(lvalue_noexcept(1, 2)));

BOOST_TEST((const_lvalue_noexcept(1, 2) == tuple(2, 1, _const_lvalue)));
BOOST_TEST(noexcept(const_lvalue_noexcept(1, 2)));

BOOST_TEST(
(transpose(test_binary_function<static_cast<member_function_qualifiers>(_all ^ _rvalue)>{})(
1, 2) == tuple(2, 1, _rvalue)));
BOOST_TEST(!noexcept(transpose(
test_binary_function<static_cast<member_function_qualifiers>(_all ^ _rvalue)>{})(1, 2)));

BOOST_TEST((transpose(test_binary_function<_rvalue>{})(1, 2) == tuple(2, 1, _rvalue)));
BOOST_TEST(noexcept(transpose(test_binary_function<_rvalue>{})(1, 2)));
}
5 changes: 5 additions & 0 deletions test/unit_tests/functional/jamfile.jam
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Jamfile for building functional test

project adobe/functional ;

run functional_test.cpp ;

0 comments on commit d9f4321

Please sign in to comment.