diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 44a3e51..e724c28 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -6,6 +6,7 @@ add_headers(core GAP_CORE_HEADERS concepts.hpp config.hpp coroutine.hpp + crtp.hpp dense_map.hpp generator.hpp hash.hpp diff --git a/core/include/gap/core/crtp.hpp b/core/include/gap/core/crtp.hpp new file mode 100644 index 0000000..28a6394 --- /dev/null +++ b/core/include/gap/core/crtp.hpp @@ -0,0 +1,20 @@ +// Copyright (c) 2024, Trail of Bits, Inc. + +#pragma once + +namespace gap::core { + + template< typename T, template< typename > class crtp_type > + struct crtp + { + T &underlying() { return static_cast< T & >(*this); } + + const T &underlying() const { return static_cast< const T & >(*this); } + + private: + crtp() {} + + friend crtp_type< T >; + }; + +} // namespace gap::core diff --git a/test/core/CMakeLists.txt b/test/core/CMakeLists.txt index 0824a5b..2a0a681 100644 --- a/test/core/CMakeLists.txt +++ b/test/core/CMakeLists.txt @@ -3,6 +3,7 @@ add_gap_test(test-gap-core bigint.cpp benchmark.cpp + crtp.cpp dense_map.cpp hash.cpp memoize.cpp diff --git a/test/core/crtp.cpp b/test/core/crtp.cpp new file mode 100644 index 0000000..6404561 --- /dev/null +++ b/test/core/crtp.cpp @@ -0,0 +1,25 @@ +// Copyright (c) 2022-present, Trail of Bits, Inc. + +#include +#include +#include + +namespace gap::test +{ + template< typename derived > + struct base : gap::core::crtp< derived, base > { + using gap::core::crtp< derived, base >::underlying; + + int foo() { return underlying().bar(); } + }; + + struct derived : base< derived > { + int bar() { return 10; } + }; + + TEST_CASE("CRTP test") { + derived d; + CHECK(d.foo() == 10); + } + +} // namespace gap::test