Skip to content

Commit

Permalink
propagate_const: Implemented the arrow operator.
Browse files Browse the repository at this point in the history
  • Loading branch information
jrgfogh committed Apr 22, 2024
1 parent 5fccd8b commit 909a477
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 18 deletions.
52 changes: 36 additions & 16 deletions sw/propagate_const.h
Original file line number Diff line number Diff line change
@@ -1,23 +1,43 @@
#pragma once

#include <utility>
#include <type_traits>
#include <memory>

template <typename T>
class propagate_const final
namespace sw
{
T t_;
public:
using element_type = int;
template <typename T>
class propagate_const final
{
T t_;
public:
using element_type = typename std::pointer_traits<T>::element_type;

constexpr propagate_const() = default;
constexpr propagate_const( propagate_const&& p ) = default;
propagate_const( const propagate_const& ) = delete;
constexpr propagate_const() = default;
constexpr propagate_const(propagate_const&&) = default;
template <class U>
constexpr explicit(!std::is_convertible<U, T>::value) propagate_const(U &&u) :
t_{std::forward<U>(u)}
{}
propagate_const(const propagate_const&) = delete;

constexpr propagate_const& operator=(propagate_const&&) = default;
template< class U >
constexpr propagate_const& operator=(U&& u)
{
t_ = std::forward<U>(u);
}
propagate_const& operator=( const propagate_const& ) = delete;
};
constexpr propagate_const& operator=(propagate_const&&) = default;
template <class U>
constexpr propagate_const& operator=(U&& u)
{
t_ = std::forward<U>(u);
return *this;
}
propagate_const& operator=(const propagate_const&) = delete;

constexpr element_type* operator->()
{
return std::to_address(t_);
}

constexpr element_type const* operator->() const
{
return std::to_address(t_);
}
};
}
62 changes: 60 additions & 2 deletions tests/propagate_const_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,65 @@ template<typename T>
concept propagate_const_specialization =
std::is_move_constructible_v<T> == std::is_move_constructible_v<typename T::element_type>
;
static_assert(propagate_const_specialization<propagate_const<int*>>);
static_assert(propagate_const_specialization<sw::propagate_const<int*>>);

TEST(PropagateConst, Exists) {
struct call_tester final
{
bool non_const_call = false;
mutable bool const_call = false;

void call() { non_const_call = true; }
void call() const { const_call = true; }
};

TEST(PropagateConst, ArrowPropagatesNonConstRawPointer)
{
call_tester ct;
sw::propagate_const<call_tester*> pc{&ct};
pc->call();
EXPECT_TRUE(ct.non_const_call);
}

TEST(PropagateConst, ArrowPropagatesConstRawPointer)
{
call_tester ct;
sw::propagate_const<call_tester*> const pc{&ct};
pc->call();
EXPECT_TRUE(ct.const_call);
}

TEST(PropagateConst, ArrowPropagatesNonConstUniquePointer)
{
auto underlying = std::make_unique<call_tester>();
call_tester &ct{*underlying};
sw::propagate_const<std::unique_ptr<call_tester>> pc{std::move(underlying)};
pc->call();
EXPECT_TRUE(ct.non_const_call);
}

TEST(PropagateConst, ArrowPropagatesConstUniquePointer)
{
auto underlying= std::make_unique<call_tester>();
call_tester &ct{*underlying};
sw::propagate_const<std::unique_ptr<call_tester>> const pc{std::move(underlying)};
pc->call();
EXPECT_TRUE(ct.const_call);
}

TEST(PropagateConst, ArrowPropagatesNonConstSharedPointer)
{
auto underlying = std::make_shared<call_tester>();
call_tester &ct{*underlying};
sw::propagate_const<std::shared_ptr<call_tester>> pc{std::move(underlying)};
pc->call();
EXPECT_TRUE(ct.non_const_call);
}

TEST(PropagateConst, ArrowPropagatesConstSharedPointer)
{
auto underlying = std::make_shared<call_tester>();
call_tester &ct{*underlying};
sw::propagate_const<std::shared_ptr<call_tester>> const pc{std::move(underlying)};
pc->call();
EXPECT_TRUE(ct.const_call);
}

0 comments on commit 909a477

Please sign in to comment.