Skip to content

Commit

Permalink
Merge pull request #12 from elbeno/generic-arity
Browse files Browse the repository at this point in the history
Generic function arity
  • Loading branch information
bdeane-intel authored Sep 21, 2023
2 parents fd4da3b + 5a47178 commit 9b5ed19
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 16 deletions.
33 changes: 23 additions & 10 deletions .github/workflows/asciidoctor-ghpages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,35 @@ env:
DEBIAN_FRONTEND: noninteractive

jobs:
build:
configure:
name: Configure Github Pages Publishing
runs-on: ubuntu-22.04
outputs:
enable_publish: ${{ steps.check.outputs.isfork == 'NO' }}
steps:
- id: check
name: Check if Fork
run: |
if [ "${{ github.repository }}" = "intel/compile-time-init-build" ]; then
echo "This is the main repository, **enabling publishing**" >> "$GITHUB_STEP_SUMMARY"
echo "isfork=NO" >> "$GITHUB_OUTPUT"
else
echo "This is a fork, **disabling publishing**" >> "$GITHUB_STEP_SUMMARY"
echo "isfork=YES" >> "$GITHUB_OUTPUT"
fi
build:
needs: configure
name: Build Documentation
runs-on: ubuntu-22.04
steps:
- name: Checkout source
uses: actions/checkout@v4

- name: Install asciidoctor
run: |
sudo apt update
sudo apt install -y asciidoctor
sudo gem install asciidoctor asciidoctor-diagram rouge
- name: Build documentation
run: |
mkdir -p ./generated-html
Expand All @@ -30,29 +46,26 @@ jobs:
touch ./generated-html/.nojekyll
ls -la ./generated-html
cat ./generated-html/index.html
- name: Setup github pages
if: needs.configure.outputs.enable_publish == 'true'
uses: actions/configure-pages@v3

- name: Upload artifacts
uses: actions/upload-pages-artifact@v2
with:
path: ./generated-html

deploy:
needs: build

needs: [configure, build]
if: needs.configure.outputs.enable_publish == 'true'
name: Deploy Documentation
permissions:
contents: read
pages: write
id-token: write

environment:
name: github-pages
url: $${{ steps.deployment.outputs.page_url }}

runs-on: ubuntu-22.04

steps:
- name: Deploy to github pages
id: deployment
Expand Down
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ project(
include(cmake/get_cpm.cmake)
cpmaddpackage("gh:intel/cicd-repo-infrastructure#main")

add_versioned_package("gh:boostorg/mp11#boost-1.83.0")

if(NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 20)
endif()
Expand All @@ -22,6 +24,7 @@ target_compile_options(
INTERFACE
$<$<CXX_COMPILER_ID:Clang>:-Wno-gnu-string-literal-operator-template>
$<$<CXX_COMPILER_ID:Clang>:-Wno-missing-braces>)
target_link_libraries_system(stdx INTERFACE boost_mp11)

if(PROJECT_IS_TOP_LEVEL)
add_docs(docs)
Expand Down
12 changes: 11 additions & 1 deletion docs/function_traits.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,23 @@ using f_args = stdx::decayed_args_t<decltype(f), std::tuple>; // std::tuple<int,
----

`stdx::arity_t` returns the arity of a function (as a `std::integral_constant`).
`stdx::arity_v` provides convenient access to the value.
[source,cpp]
----
auto f(int&, std::string&) -> void {}
using f_arity = stdx::arity_t<decltype(f)>; // std::integral_constant<std::size_t, 2>
using f_arity_t = stdx::arity_t<decltype(f)>; // std::integral_constant<std::size_t, 2>
constexpr auto f_arity_v = stdx::arity_v<decltype(f)>;
----


NOTE: Function traits work on functions (and function objects): not function
templates or overload sets. For instance therefore, they will not work on generic
lambda expressions.

The one exception to this is `stdx::arity_t` - it works on generic lambdas.
[source,cpp]
----
auto l = [](auto, auto) -> void {};
using f_arity_t = stdx::arity_t<decltype(l)>; // std::integral_constant<std::size_t, 2>
constexpr auto f_arity_v = stdx::arity_v<decltype(l)>;
----
8 changes: 4 additions & 4 deletions include/stdx/bitset.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ template <std::size_t N, typename StorageElem> class bitset {
constexpr auto set(std::size_t pos, bool value = true) -> bitset & {
auto const [index, offset] = indices(pos);
if (value) {
storage[index] |= (bit << offset);
storage[index] |= static_cast<StorageElem>(bit << offset);
} else {
storage[index] &= static_cast<StorageElem>(~(bit << offset));
}
Expand Down Expand Up @@ -195,7 +195,7 @@ template <std::size_t N, typename StorageElem> class bitset {

constexpr auto flip(std::size_t pos) -> bitset & {
auto const [index, offset] = indices(pos);
storage[index] ^= bit << offset;
storage[index] ^= static_cast<StorageElem>(bit << offset);
return *this;
}

Expand Down Expand Up @@ -300,13 +300,13 @@ template <std::size_t N, typename StorageElem> class bitset {
} else {
auto const borrow_shift = storage_elem_size - pos;
for (auto i = start; i < storage_size - 1; ++i) {
storage[dst] = storage[i] >> pos;
storage[dst] = static_cast<StorageElem>(storage[i] >> pos);
storage[dst] |=
static_cast<StorageElem>(storage[i + 1] << borrow_shift);
++dst;
}
}
storage[dst++] = storage.back() >> pos;
storage[dst++] = static_cast<StorageElem>(storage.back() >> pos);
while (dst < storage_size) {
storage[dst++] = 0;
}
Expand Down
39 changes: 38 additions & 1 deletion include/stdx/function_traits.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include <boost/mp11/utility.hpp>

#include <functional>
#include <type_traits>
#include <utility>
Expand Down Expand Up @@ -29,7 +31,42 @@ template <typename F, template <typename...> typename List>
using args_t = typename function_traits<F>::template args<List>;
template <typename F, template <typename...> typename List>
using decayed_args_t = typename function_traits<F>::template decayed_args<List>;
template <typename F> using arity_t = typename function_traits<F>::arity;
template <typename F>
using nongeneric_arity_t = typename function_traits<F>::arity;

namespace detail {
template <auto> struct any_type {
// NOLINTNEXTLINE(google-explicit-constructor)
template <typename T> operator T();
};

template <typename F, std::size_t... Is>
constexpr auto try_invoke_impl(std::index_sequence<Is...>)
-> std::invoke_result_t<F, any_type<Is>...>;

template <typename F, typename N>
using try_invoke =
decltype(try_invoke_impl<F>(std::make_index_sequence<N::value>{}));

template <typename F, typename N>
using has_arg_count = boost::mp11::mp_valid<try_invoke, F, N>;

template <typename F, typename N> struct generic_arity;

template <typename F, typename N>
using generic_arity_t = typename generic_arity<F, N>::type;

template <typename F, typename N> struct generic_arity {
using type = boost::mp11::mp_eval_if<
has_arg_count<F, N>, N, generic_arity_t, F,
std::integral_constant<std::size_t, N::value + 1u>>;
};
} // namespace detail

template <typename F>
using arity_t = boost::mp11::mp_eval_or<
detail::generic_arity_t<F, std::integral_constant<std::size_t, 0u>>,
nongeneric_arity_t, F>;
template <typename F> constexpr auto arity_v = arity_t<F>::value;
} // namespace v1
} // namespace stdx
16 changes: 16 additions & 0 deletions test/function_traits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ TEST_CASE("function arity", "[function_traits]") {
1u);
static_assert(stdx::arity_t<decltype(func_no_args)>::value == 0u);
static_assert(stdx::arity_t<decltype(func_one_arg)>::value == 1u);

static_assert(stdx::arity_v<decltype(func_no_args)> == 0u);
static_assert(stdx::arity_v<decltype(func_one_arg)> == 1u);
}

TEST_CASE("lambda arity", "[function_traits]") {
Expand All @@ -113,6 +116,19 @@ TEST_CASE("lambda arity", "[function_traits]") {
static_assert(stdx::function_traits<decltype(y)>::arity::value == 1u);
static_assert(stdx::arity_t<decltype(x)>::value == 0u);
static_assert(stdx::arity_t<decltype(y)>::value == 1u);

static_assert(stdx::arity_v<decltype(x)> == 0u);
static_assert(stdx::arity_v<decltype(y)> == 1u);
}

TEST_CASE("generic lambda arity", "[function_traits]") {
[[maybe_unused]] auto const x = [](auto) {};
[[maybe_unused]] auto const y = [](auto, auto) {};
static_assert(stdx::arity_t<decltype(x)>::value == 1u);
static_assert(stdx::arity_t<decltype(y)>::value == 2u);

static_assert(stdx::arity_v<decltype(x)> == 1u);
static_assert(stdx::arity_v<decltype(y)> == 2u);
}

namespace {
Expand Down

0 comments on commit 9b5ed19

Please sign in to comment.