Skip to content

Commit 57c0bb0

Browse files
authored
Merge pull request #13 from cschreib/observer_constructor
Add casting from owner constructor to basic_observer_ptr
2 parents 08f687f + 3f64587 commit 57c0bb0

File tree

3 files changed

+119
-13
lines changed

3 files changed

+119
-13
lines changed

.github/workflows/cmake.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939
- name: Setup Emscripten cache
4040
if: matrix.platform.compiler == 'em++'
4141
id: cache-system-libraries
42-
uses: actions/cache@v2.1.7
42+
uses: actions/cache@v3.0.4
4343
with:
4444
path: ${{env.EM_CACHE_FOLDER}}
4545
key: ${{env.EM_VERSION}}-${{ runner.os }}

include/oup/observable_unique_ptr.hpp

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,10 @@ class basic_observer_ptr final {
969969
}
970970
}
971971

972-
/// Create an observer pointer from an owning pointer.
972+
/**
973+
* \brief Create an observer pointer from an owning pointer of a convertible type.
974+
* \param owner The owner pointer to observe (can be null)
975+
*/
973976
template<
974977
typename U,
975978
typename D,
@@ -983,6 +986,26 @@ class basic_observer_ptr final {
983986
}
984987
}
985988

989+
/**
990+
* \brief Create an observer pointer from an owning pointer of a different type.
991+
* \param manager The owner pointer to copy the observed data from
992+
* \param value The casted pointer value to observe
993+
* \note The raw pointer `value` may or may not be related to the raw pointer
994+
* owner by `manager`. This could be a pointer to any other object which is known
995+
* to have the same lifetime.
996+
*/
997+
template<
998+
typename U,
999+
typename D,
1000+
typename P,
1001+
typename enable = std::enable_if_t<std::is_same_v<Policy, typename P::observer_policy>>>
1002+
basic_observer_ptr(const basic_observable_ptr<U, D, P>& manager, T* value) noexcept :
1003+
block(manager.block), data(value) {
1004+
if (block) {
1005+
block->push_ref();
1006+
}
1007+
}
1008+
9861009
/**
9871010
* \brief Copy an existing @ref basic_observer_ptr instance
9881011
* \param value The existing observer pointer to copy
@@ -1010,12 +1033,9 @@ class basic_observer_ptr final {
10101033
* \brief Copy an existing @ref basic_observer_ptr instance with explicit casting
10111034
* \param manager The observer pointer to copy the observed data from
10121035
* \param value The casted pointer value to observe
1013-
* \note After this smart pointer is created, the source
1014-
* pointer is set to null and looses ownership. The deleter
1015-
* is default constructed. The raw pointer `value` may or may
1016-
* not be related to the raw pointer observed by `manager`.
1017-
* This could be a pointer to any other object which is known to
1018-
* have the same lifetime.
1036+
* \note The raw pointer `value` may or may not be related to the raw pointer
1037+
* observed by `manager`. This could be a pointer to any other object which is known
1038+
* to have the same lifetime.
10191039
*/
10201040
template<typename U>
10211041
basic_observer_ptr(const basic_observer_ptr<U, Policy>& manager, T* value) noexcept :
@@ -1054,11 +1074,9 @@ class basic_observer_ptr final {
10541074
* \brief Move from an existing @ref basic_observer_ptr instance with explicit casting
10551075
* \param manager The observer pointer to copy the observed data from
10561076
* \param value The casted pointer value to observe
1057-
* \note After this smart pointer is created, the source
1058-
* pointer is set to null and looses ownership. The deleter
1059-
* is default constructed. The raw pointer `value` may or may
1060-
* not be related to the raw pointer observed by `manager`.
1061-
* This could be a pointer to any other object which is known to
1077+
* \note After this smart pointer is created, the source pointer `manager` is set to
1078+
* null. The raw pointer `value` may or may not be related to the raw pointer observed
1079+
* by `manager`. This could be a pointer to any other object which is known to
10621080
* have the same lifetime.
10631081
*/
10641082
template<typename U>

tests/runtime_tests.cpp

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1949,6 +1949,94 @@ TEST_CASE("observer explicit conversion copy constructor subobject", "[observer_
19491949
REQUIRE(mem_track.double_del() == 0u);
19501950
}
19511951

1952+
TEST_CASE("observer from null owner constructor", "[observer_construction]") {
1953+
memory_tracker mem_track;
1954+
1955+
{
1956+
test_ptr ptr_owner;
1957+
{
1958+
test_optr ptr{ptr_owner};
1959+
REQUIRE(instances == 0);
1960+
REQUIRE(ptr.get() == ptr_owner.get());
1961+
REQUIRE(ptr.expired() == true);
1962+
}
1963+
1964+
REQUIRE(instances == 0);
1965+
}
1966+
1967+
REQUIRE(instances == 0);
1968+
REQUIRE(mem_track.leaks() == 0u);
1969+
REQUIRE(mem_track.double_del() == 0u);
1970+
}
1971+
1972+
TEST_CASE("observer from owner constructor", "[observer_construction]") {
1973+
memory_tracker mem_track;
1974+
1975+
{
1976+
test_ptr ptr_owner{new test_object};
1977+
{
1978+
test_optr ptr{ptr_owner};
1979+
REQUIRE(instances == 1);
1980+
REQUIRE(ptr.get() == ptr_owner.get());
1981+
REQUIRE(ptr.expired() == false);
1982+
1983+
ptr_owner.reset();
1984+
REQUIRE(ptr.get() == nullptr);
1985+
REQUIRE(ptr.expired() == true);
1986+
}
1987+
1988+
REQUIRE(instances == 0);
1989+
}
1990+
1991+
REQUIRE(instances == 0);
1992+
REQUIRE(mem_track.leaks() == 0u);
1993+
REQUIRE(mem_track.double_del() == 0u);
1994+
}
1995+
1996+
TEST_CASE("observer from null owner casting constructor", "[observer_construction]") {
1997+
memory_tracker mem_track;
1998+
1999+
{
2000+
test_ptr ptr_owner;
2001+
{
2002+
test_optr ptr{ptr_owner, static_cast<test_object*>(nullptr)};
2003+
REQUIRE(instances == 0);
2004+
REQUIRE(ptr.get() == ptr_owner.get());
2005+
REQUIRE(ptr.expired() == true);
2006+
}
2007+
2008+
REQUIRE(instances == 0);
2009+
}
2010+
2011+
REQUIRE(instances == 0);
2012+
REQUIRE(mem_track.leaks() == 0u);
2013+
REQUIRE(mem_track.double_del() == 0u);
2014+
}
2015+
2016+
TEST_CASE("observer from owner casting constructor", "[observer_construction]") {
2017+
memory_tracker mem_track;
2018+
2019+
{
2020+
test_ptr ptr_owner{new test_object_derived};
2021+
{
2022+
test_optr ptr{ptr_owner, dynamic_cast<test_object_derived*>(ptr_owner.get())};
2023+
REQUIRE(instances == 1);
2024+
REQUIRE(ptr.get() == ptr_owner.get());
2025+
REQUIRE(ptr.expired() == false);
2026+
2027+
ptr_owner.reset();
2028+
REQUIRE(ptr.get() == nullptr);
2029+
REQUIRE(ptr.expired() == true);
2030+
}
2031+
2032+
REQUIRE(instances == 0);
2033+
}
2034+
2035+
REQUIRE(instances == 0);
2036+
REQUIRE(mem_track.leaks() == 0u);
2037+
REQUIRE(mem_track.double_del() == 0u);
2038+
}
2039+
19522040
TEST_CASE("observer move constructor", "[observer_construction]") {
19532041
memory_tracker mem_track;
19542042

0 commit comments

Comments
 (0)