Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 44 additions & 5 deletions doc/modules/ROOT/examples/shared_libs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ message(STATUS "Boost.OpenMethod: building shared library examples")

add_compile_definitions(BOOST_OPENMETHOD_ENABLE_RUNTIME_CHECKS)

# All targets output to the same directory so that executables can locate shared
# libraries via boost::dll::program_location().parent_path().
set(shared_libs_output_dir "${CMAKE_CURRENT_BINARY_DIR}")

# Helper: add a CTest fixture that builds a CMake target, so that `ctest` alone
# (without a prior `cmake --build`) still works.
function(openmethod_shared_libs_build_fixture target)
add_test(NAME ${target}-build
COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_BINARY_DIR}"
--target ${target} --config $<CONFIG>)
set_tests_properties(${target}-build PROPERTIES FIXTURES_SETUP ${target}-fixture)
endfunction()

# ------------------------------------------------------------------------------
# static linking

Expand All @@ -15,21 +28,38 @@ target_link_libraries(boost_openmethod-shared Boost::openmethod)
set_target_properties(boost_openmethod-shared PROPERTIES
ENABLE_EXPORTS ON
OUTPUT_NAME shared
LIBRARY_OUTPUT_DIRECTORY "${shared_libs_output_dir}"
RUNTIME_OUTPUT_DIRECTORY "${shared_libs_output_dir}"
)

add_executable(boost_openmethod-static static_main.cpp)
target_link_libraries(boost_openmethod-static Boost::openmethod Boost::dll boost_openmethod-shared)
add_test(NAME boost_openmethod-static COMMAND boost_openmethod-static)
set_target_properties(boost_openmethod-static PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${shared_libs_output_dir}"
)
openmethod_shared_libs_build_fixture(boost_openmethod-static)
add_test(NAME boost_openmethod-static
COMMAND "${shared_libs_output_dir}/boost_openmethod-static")
set_tests_properties(boost_openmethod-static PROPERTIES
FIXTURES_REQUIRED boost_openmethod-static-fixture)
Comment on lines +41 to +44
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test command hardcodes the executable path as ${shared_libs_output_dir}/boost_openmethod-static. This is not robust on Windows (missing .exe) and can also break on multi-config generators where outputs may be placed under a per-config subdirectory. Prefer using $<TARGET_FILE:boost_openmethod-static> (and similarly for the other executables) so CTest runs the actual built artifact regardless of platform/config.

Copilot uses AI. Check for mistakes.

# ------------------------------------------------------------------------------
# dynamic loading, direct virtual_ptrs

add_executable(boost_openmethod-dynamic dynamic_main.cpp)
set_target_properties(boost_openmethod-dynamic PROPERTIES ENABLE_EXPORTS ON)
set_target_properties(boost_openmethod-dynamic PROPERTIES
ENABLE_EXPORTS ON
RUNTIME_OUTPUT_DIRECTORY "${shared_libs_output_dir}"
)
target_link_libraries(boost_openmethod-dynamic Boost::openmethod Boost::dll)
add_dependencies(boost_openmethod-dynamic boost_openmethod-shared)
if (NOT WIN32)
add_test(NAME boost_openmethod-dynamic COMMAND boost_openmethod-dynamic)
openmethod_shared_libs_build_fixture(boost_openmethod-shared)
openmethod_shared_libs_build_fixture(boost_openmethod-dynamic)
add_test(NAME boost_openmethod-dynamic
COMMAND "${shared_libs_output_dir}/boost_openmethod-dynamic")
set_tests_properties(boost_openmethod-dynamic PROPERTIES
FIXTURES_REQUIRED "boost_openmethod-shared-fixture;boost_openmethod-dynamic-fixture")
Comment on lines +59 to +62
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test command uses a manually constructed path ${shared_libs_output_dir}/boost_openmethod-dynamic, which can fail on platforms/configurations where the executable filename includes an extension (e.g., .exe) or is placed in a config-specific output directory. Use $<TARGET_FILE:boost_openmethod-dynamic> to make the test invocation generator- and platform-independent.

Copilot uses AI. Check for mistakes.
endif()

# ------------------------------------------------------------------------------
Expand All @@ -42,14 +72,23 @@ target_link_libraries(boost_openmethod-indirect_shared PRIVATE Boost::openmethod
set_target_properties(boost_openmethod-indirect_shared PROPERTIES
ENABLE_EXPORTS ON
OUTPUT_NAME indirect_shared
LIBRARY_OUTPUT_DIRECTORY "${shared_libs_output_dir}"
RUNTIME_OUTPUT_DIRECTORY "${shared_libs_output_dir}"
)

add_executable(boost_openmethod-indirect indirect_main.cpp)
target_compile_definitions(
boost_openmethod-indirect PUBLIC BOOST_OPENMETHOD_DEFAULT_REGISTRY=indirect_registry)
set_target_properties(boost_openmethod-indirect PROPERTIES ENABLE_EXPORTS ON)
set_target_properties(boost_openmethod-indirect PROPERTIES
ENABLE_EXPORTS ON
RUNTIME_OUTPUT_DIRECTORY "${shared_libs_output_dir}"
)
target_link_libraries(boost_openmethod-indirect PRIVATE Boost::openmethod Boost::dll)
add_dependencies(boost_openmethod-indirect boost_openmethod-indirect_shared)
if (NOT WIN32)
add_test(NAME boost_openmethod-indirect COMMAND boost_openmethod-indirect)
openmethod_shared_libs_build_fixture(boost_openmethod-indirect)
add_test(NAME boost_openmethod-indirect
COMMAND "${shared_libs_output_dir}/boost_openmethod-indirect")
set_tests_properties(boost_openmethod-indirect PROPERTIES
FIXTURES_REQUIRED boost_openmethod-indirect-fixture)
Comment on lines +90 to +93
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test command uses ${shared_libs_output_dir}/boost_openmethod-indirect, which may not exist as-is on Windows (extension) or with multi-config output layouts. Using $<TARGET_FILE:boost_openmethod-indirect> will ensure CTest executes the correct built binary.

Copilot uses AI. Check for mistakes.
endif()
17 changes: 14 additions & 3 deletions include/boost/openmethod/macros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ struct va_args<ReturnType> {
using registry = macro_default_registry;
};

template<typename...>
inline constexpr bool method_not_found = false;

} // namespace boost::openmethod::detail

#define BOOST_OPENMETHOD_GENSYM BOOST_PP_CAT(openmethod_gensym_, __COUNTER__)
Expand Down Expand Up @@ -82,10 +85,18 @@ struct va_args<ReturnType> {
struct BOOST_OPENMETHOD_OVERRIDERS(NAME)

#define BOOST_OPENMETHOD_DETAIL_LOCATE_METHOD(NAME, ARGS) \
template<typename T> \
struct boost_openmethod_detail_locate_method_aux; \
template<typename T, typename = void> \
struct boost_openmethod_detail_locate_method_aux { \
static_assert( \
::boost::openmethod::detail::method_not_found<T>, \
"BOOST_OPENMETHOD_OVERRIDE: cannot find '" #NAME \
"' method that accepts the same arguments as the overrider"); \
}; \
template<typename... A> \
struct boost_openmethod_detail_locate_method_aux<void(A...)> { \
struct boost_openmethod_detail_locate_method_aux< \
void(A...), \
std::void_t<decltype(BOOST_OPENMETHOD_GUIDE(NAME)( \
std::declval<A>()...))>> { \
using type = \
decltype(BOOST_OPENMETHOD_GUIDE(NAME)(std::declval<A>()...)); \
}
Expand Down
2 changes: 2 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,5 @@ openmethod_compile_fail_test(
compile_fail_virtual_parameter_private_base_core "must be an unambiguous accessible base")
openmethod_compile_fail_test(
compile_fail_repeated_inheritance "repeated inheritance")
openmethod_compile_fail_test(
compile_fail_override_method_not_found "cannot find 'speak' method that accepts the same arguments as the overrider")
Comment on lines +105 to +106
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This compile-fail test target references a source file compile_fail_override_method_not_found.cpp, but that file is not present under test/ in this PR. As-is, CMake configuration/build will fail because add_library(... "${testname}.cpp") points to a non-existent file. Please add the missing test/compile_fail_override_method_not_found.cpp (and ensure it triggers the new diagnostic), or remove this test registration.

Suggested change
openmethod_compile_fail_test(
compile_fail_override_method_not_found "cannot find 'speak' method that accepts the same arguments as the overrider")

Copilot uses AI. Check for mistakes.
22 changes: 22 additions & 0 deletions test/compile_fail_override_method_not_found.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) 2018-2025 Jean-Louis Leroy
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)

#include <boost/openmethod.hpp>

using boost::openmethod::virtual_;

struct Animal {};
struct Dog : Animal {};

// Deliberately omit BOOST_OPENMETHOD(speak, ...) to trigger the static_assert.

BOOST_OPENMETHOD_CLASSES(Animal, Dog);

BOOST_OPENMETHOD_OVERRIDE(speak, (virtual_<Dog&>), void) {
}

int main() {
return 0;
}
Loading