Skip to content

Commit

Permalink
deduce
Browse files Browse the repository at this point in the history
Extension for working well with CTAD.
  • Loading branch information
RobertLeahy committed Feb 1, 2025
1 parent 0e1a55e commit 73732e0
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 1 deletion.
34 changes: 34 additions & 0 deletions include/beman/elide/deduce.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#ifndef BEMAN_ELIDE_DEDUCE_HPP
#define BEMAN_ELIDE_DEDUCE_HPP

#include <type_traits>
#include <beman/elide/elide.hpp>

namespace beman::elide {

namespace detail::deduce {

template<typename>
struct is_elide : std::false_type {};
template<typename T, typename... Args>
struct is_elide<beman::elide::elide<T, Args...>> : std::true_type {};

}

template<typename T>
struct deduce : std::remove_cvref<T> {};
template<typename T>
requires
detail::deduce::is_elide<
std::remove_cvref_t<T>>::value &&
std::is_invocable_v<T>
struct deduce<T> : std::invoke_result<T> {};

template<typename T>
using deduce_t = typename deduce<T>::type;

} // namespace beman::elide

#endif // BEMAN_ELIDE_DEDUCE_HPP
4 changes: 3 additions & 1 deletion src/beman/elide/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ target_sources(
PUBLIC
FILE_SET HEADERS
BASE_DIRS ${PROJECT_SOURCE_DIR}/include
FILES ${PROJECT_SOURCE_DIR}/include/beman/elide/elide.hpp
FILES
${PROJECT_SOURCE_DIR}/include/beman/elide/deduce.hpp
${PROJECT_SOURCE_DIR}/include/beman/elide/elide.hpp
)

set_target_properties(beman.elide PROPERTIES VERIFY_INTERFACE_HEADER_SETS ON)
Expand Down
9 changes: 9 additions & 0 deletions tests/beman/elide/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,12 @@ target_link_libraries(
)

gtest_add_tests(beman.elide.tests.elide "" AUTO)

add_executable(beman.elide.tests.deduce)
target_sources(beman.elide.tests.deduce PRIVATE deduce.test.cpp)
target_link_libraries(
beman.elide.tests.deduce
PRIVATE beman::elide GTest::gtest GTest::gtest_main
)

gtest_add_tests(beman.elide.tests.deduce "" AUTO)
134 changes: 134 additions & 0 deletions tests/beman/elide/deduce.test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <beman/elide/deduce.hpp>

#include <type_traits>
#include <utility>
#include <beman/elide/elide.hpp>

#include <gtest/gtest.h>

namespace beman::elide {

namespace {

struct factory {
int operator()();
};

struct no_lvalue_factory {
int operator()() &&;
};

struct split_factory {
int operator()() &;
double operator()() &&;
};

template<typename T>
struct wrapper {
template<typename U>
explicit wrapper(U&& u) noexcept(
std::is_nothrow_constructible_v<T, U>)
: t_(std::forward<U>(u))
{}
constexpr const T& get() const noexcept {
return t_;
}
private:
T t_;
};

template<typename T>
explicit wrapper(T&&) -> wrapper<deduce_t<T>>;

}

static_assert(!detail::deduce::is_elide<int>::value);
static_assert(detail::deduce::is_elide<elide<factory&>>::value);

static_assert(std::is_same_v<int, deduce_t<int>>);
static_assert(std::is_same_v<int, deduce_t<int&>>);
static_assert(std::is_same_v<int, deduce_t<const int&>>);
static_assert(std::is_same_v<int, deduce_t<int&&>>);
static_assert(std::is_same_v<int, deduce_t<const int&&>>);

static_assert(
std::is_same_v<
int,
deduce_t<
elide<factory&>>>);
static_assert(
std::is_same_v<
int,
deduce_t<
elide<factory&>&>>);
static_assert(
std::is_same_v<
int,
deduce_t<
const elide<factory&>&>>);
static_assert(
std::is_same_v<
int,
deduce_t<
elide<factory&>&&>>);
static_assert(
std::is_same_v<
int,
deduce_t<
const elide<factory&>&&>>);

static_assert(
std::is_same_v<
int,
deduce_t<
elide<no_lvalue_factory&&>>>);
static_assert(
std::is_same_v<
int,
deduce_t<
elide<no_lvalue_factory&&>&&>>);
static_assert(
std::is_same_v<
int,
deduce_t<
const elide<no_lvalue_factory&&>&&>>);
static_assert(
std::is_same_v<
elide<no_lvalue_factory&&>,
deduce_t<
const elide<no_lvalue_factory&&>&>>);
static_assert(
std::is_same_v<
elide<no_lvalue_factory&&>,
deduce_t<
elide<no_lvalue_factory&&>&>>);

static_assert(
std::is_same_v<
double,
deduce_t<
elide<split_factory&&>>>);
static_assert(
std::is_same_v<
double,
deduce_t<
elide<split_factory&&>&&>>);
static_assert(
std::is_same_v<
int,
std::invoke_result_t<
elide<split_factory&&>&>>);
static_assert(
std::is_same_v<
int,
deduce_t<
elide<split_factory&&>&>>);

TEST(Deduce, basic) {
wrapper w(elide([]() noexcept { return 5; }));
EXPECT_EQ(5, w.get());
}

}

0 comments on commit 73732e0

Please sign in to comment.