Skip to content

Commit 83fce13

Browse files
committed
Fix issue #767 and #768
1 parent 3326553 commit 83fce13

File tree

2 files changed

+52
-19
lines changed

2 files changed

+52
-19
lines changed

include/behaviortree_cpp/basic_types.h

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,39 @@ inline std::pair<std::string, PortInfo> BidirectionalPort(StringView name,
425425
return CreatePort<T>(PortDirection::INOUT, name, description);
426426
}
427427
//----------
428+
429+
namespace details {
430+
431+
template <typename T = AnyTypeAllowed, typename DefaultT = T> [[nodiscard]]
432+
inline std::pair<std::string, PortInfo> PortWithDefault(
433+
PortDirection direction,
434+
StringView name,
435+
const DefaultT& default_value,
436+
StringView description)
437+
{
438+
static_assert(IsConvertibleToString<DefaultT>() ||
439+
std::is_convertible_v<T, DefaultT> ||
440+
std::is_constructible_v<T, DefaultT>,
441+
"The default value must be either the same of the port or string");
442+
443+
auto out = CreatePort<T>(direction, name, description);
444+
445+
if constexpr(std::is_constructible_v<T, DefaultT>)
446+
{
447+
out.second.setDefaultValue(T(default_value));
448+
}
449+
else if constexpr(IsConvertibleToString<DefaultT>())
450+
{
451+
out.second.setDefaultValue(std::string(default_value));
452+
}
453+
else {
454+
out.second.setDefaultValue(default_value);
455+
}
456+
return out;
457+
}
458+
459+
} // end namespace details
460+
428461
/** Syntactic sugar to invoke CreatePort<T>(PortDirection::INPUT,...)
429462
* It also sets the PortInfo::defaultValue()
430463
*
@@ -437,14 +470,7 @@ inline std::pair<std::string, PortInfo> InputPort(StringView name,
437470
const DefaultT& default_value,
438471
StringView description)
439472
{
440-
static_assert(std::is_same_v<T, DefaultT> ||
441-
IsConvertibleToString<DefaultT>() ||
442-
std::is_convertible_v<DefaultT, T>,
443-
"The default value must be either the same of the port or a string");
444-
445-
auto out = CreatePort<T>(PortDirection::INPUT, name, description);
446-
out.second.setDefaultValue(default_value);
447-
return out;
473+
return details::PortWithDefault<T, DefaultT>(PortDirection::INPUT, name, default_value, description);
448474
}
449475

450476
/** Syntactic sugar to invoke CreatePort<T>(PortDirection::INOUT,...)
@@ -459,14 +485,7 @@ inline std::pair<std::string, PortInfo> BidirectionalPort(StringView name,
459485
const DefaultT& default_value,
460486
StringView description)
461487
{
462-
static_assert(std::is_same_v<T, DefaultT> ||
463-
IsConvertibleToString<DefaultT>() ||
464-
std::is_convertible_v<DefaultT, T>,
465-
"The default value must be either the same of the port or a string");
466-
467-
auto out = CreatePort<T>(PortDirection::INOUT, name, description);
468-
out.second.setDefaultValue(default_value);
469-
return out;
488+
return details::PortWithDefault<T, DefaultT>(PortDirection::INOUT, name, default_value, description);
470489
}
471490

472491
/** Syntactic sugar to invoke CreatePort<T>(PortDirection::OUTPUT,...)
@@ -477,9 +496,10 @@ inline std::pair<std::string, PortInfo> BidirectionalPort(StringView name,
477496
* @param description optional human-readable description
478497
*/
479498
template <typename T = AnyTypeAllowed> [[nodiscard]]
480-
inline std::pair<std::string, PortInfo> OutputPort(StringView name,
481-
StringView default_value,
482-
StringView description)
499+
inline std::pair<std::string, PortInfo> OutputPort(
500+
StringView name,
501+
StringView default_value,
502+
StringView description)
483503
{
484504
if(default_value.empty() || default_value.front() != '{' || default_value.back() != '}')
485505
{

tests/gtest_ports.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,3 +533,16 @@ TEST(PortTest, DefaultInputStrings)
533533
ASSERT_EQ(status, NodeStatus::SUCCESS);
534534
}
535535

536+
537+
TEST(PortTest, Default_Issues_767_768)
538+
{
539+
using namespace BT;
540+
541+
ASSERT_NO_THROW(auto p = InputPort<std::optional<Point2D>>("opt_A", std::nullopt, "default nullopt"));
542+
ASSERT_NO_THROW(auto p = InputPort<std::optional<std::string>>("opt_B", std::nullopt, "default nullopt"));
543+
544+
ASSERT_NO_THROW(auto p = InputPort<std::shared_ptr<Point2D>>("ptr_A", nullptr, "default nullptr"));
545+
ASSERT_NO_THROW(auto p = InputPort<std::shared_ptr<std::string>>("ptr_B", nullptr, "default nullptr"));
546+
}
547+
548+

0 commit comments

Comments
 (0)