From 83fce13a38efe81f2dd5713328f94942f32f8c9a Mon Sep 17 00:00:00 2001 From: Davide Faconti Date: Tue, 13 Feb 2024 11:28:57 +0100 Subject: [PATCH] Fix issue #767 and #768 --- include/behaviortree_cpp/basic_types.h | 58 +++++++++++++++++--------- tests/gtest_ports.cpp | 13 ++++++ 2 files changed, 52 insertions(+), 19 deletions(-) diff --git a/include/behaviortree_cpp/basic_types.h b/include/behaviortree_cpp/basic_types.h index e0763c49a..4c179e34e 100644 --- a/include/behaviortree_cpp/basic_types.h +++ b/include/behaviortree_cpp/basic_types.h @@ -425,6 +425,39 @@ inline std::pair BidirectionalPort(StringView name, return CreatePort(PortDirection::INOUT, name, description); } //---------- + +namespace details { + +template [[nodiscard]] +inline std::pair PortWithDefault( + PortDirection direction, + StringView name, + const DefaultT& default_value, + StringView description) +{ + static_assert(IsConvertibleToString() || + std::is_convertible_v || + std::is_constructible_v, + "The default value must be either the same of the port or string"); + + auto out = CreatePort(direction, name, description); + + if constexpr(std::is_constructible_v) + { + out.second.setDefaultValue(T(default_value)); + } + else if constexpr(IsConvertibleToString()) + { + out.second.setDefaultValue(std::string(default_value)); + } + else { + out.second.setDefaultValue(default_value); + } + return out; +} + +} // end namespace details + /** Syntactic sugar to invoke CreatePort(PortDirection::INPUT,...) * It also sets the PortInfo::defaultValue() * @@ -437,14 +470,7 @@ inline std::pair InputPort(StringView name, const DefaultT& default_value, StringView description) { - static_assert(std::is_same_v || - IsConvertibleToString() || - std::is_convertible_v, - "The default value must be either the same of the port or a string"); - - auto out = CreatePort(PortDirection::INPUT, name, description); - out.second.setDefaultValue(default_value); - return out; + return details::PortWithDefault(PortDirection::INPUT, name, default_value, description); } /** Syntactic sugar to invoke CreatePort(PortDirection::INOUT,...) @@ -459,14 +485,7 @@ inline std::pair BidirectionalPort(StringView name, const DefaultT& default_value, StringView description) { - static_assert(std::is_same_v || - IsConvertibleToString() || - std::is_convertible_v, - "The default value must be either the same of the port or a string"); - - auto out = CreatePort(PortDirection::INOUT, name, description); - out.second.setDefaultValue(default_value); - return out; + return details::PortWithDefault(PortDirection::INOUT, name, default_value, description); } /** Syntactic sugar to invoke CreatePort(PortDirection::OUTPUT,...) @@ -477,9 +496,10 @@ inline std::pair BidirectionalPort(StringView name, * @param description optional human-readable description */ template [[nodiscard]] -inline std::pair OutputPort(StringView name, - StringView default_value, - StringView description) +inline std::pair OutputPort( + StringView name, + StringView default_value, + StringView description) { if(default_value.empty() || default_value.front() != '{' || default_value.back() != '}') { diff --git a/tests/gtest_ports.cpp b/tests/gtest_ports.cpp index 9b829ff26..0efbb4cc8 100644 --- a/tests/gtest_ports.cpp +++ b/tests/gtest_ports.cpp @@ -533,3 +533,16 @@ TEST(PortTest, DefaultInputStrings) ASSERT_EQ(status, NodeStatus::SUCCESS); } + +TEST(PortTest, Default_Issues_767_768) +{ + using namespace BT; + + ASSERT_NO_THROW(auto p = InputPort>("opt_A", std::nullopt, "default nullopt")); + ASSERT_NO_THROW(auto p = InputPort>("opt_B", std::nullopt, "default nullopt")); + + ASSERT_NO_THROW(auto p = InputPort>("ptr_A", nullptr, "default nullptr")); + ASSERT_NO_THROW(auto p = InputPort>("ptr_B", nullptr, "default nullptr")); +} + +