Merge pull request #122 from ros2/expression-sfinae-windows
Work around VS2015's broken support for expression SFINAE
This commit is contained in:
commit
ae682baf1c
5 changed files with 435 additions and 89 deletions
|
@ -22,6 +22,7 @@ if(AMENT_ENABLE_TESTING)
|
||||||
|
|
||||||
include_directories(include)
|
include_directories(include)
|
||||||
|
|
||||||
|
ament_add_gtest(test_function_traits test/test_function_traits.cpp)
|
||||||
ament_add_gtest(test_mapped_ring_buffer test/test_mapped_ring_buffer.cpp)
|
ament_add_gtest(test_mapped_ring_buffer test/test_mapped_ring_buffer.cpp)
|
||||||
ament_add_gtest(test_intra_process_manager test/test_intra_process_manager.cpp)
|
ament_add_gtest(test_intra_process_manager test/test_intra_process_manager.cpp)
|
||||||
if(TARGET test_intra_process_manager)
|
if(TARGET test_intra_process_manager)
|
||||||
|
|
|
@ -57,75 +57,83 @@ struct AnySubscriptionCallback
|
||||||
|
|
||||||
AnySubscriptionCallback(const AnySubscriptionCallback &) = default;
|
AnySubscriptionCallback(const AnySubscriptionCallback &) = default;
|
||||||
|
|
||||||
template<typename CallbackT,
|
template<
|
||||||
typename std::enable_if<
|
typename CallbackT,
|
||||||
function_traits<CallbackT>::arity == 1
|
std::size_t Arity = 1
|
||||||
>::type * = nullptr,
|
|
||||||
typename std::enable_if<
|
|
||||||
std::is_same<
|
|
||||||
typename function_traits<CallbackT>::template argument_type<0>,
|
|
||||||
typename std::shared_ptr<MessageT>
|
|
||||||
>::value
|
|
||||||
>::type * = nullptr
|
|
||||||
>
|
>
|
||||||
void set(CallbackT callback)
|
typename std::enable_if<rclcpp::arity_comparator<Arity, CallbackT>::value, void>::type
|
||||||
|
set(
|
||||||
|
CallbackT callback,
|
||||||
|
typename std::enable_if<
|
||||||
|
std::is_same<
|
||||||
|
typename function_traits<CallbackT>::template argument_type<0>,
|
||||||
|
typename std::shared_ptr<MessageT>
|
||||||
|
>::value
|
||||||
|
>::type * = nullptr)
|
||||||
{
|
{
|
||||||
shared_ptr_callback = callback;
|
shared_ptr_callback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename CallbackT,
|
template<
|
||||||
typename std::enable_if<
|
typename CallbackT,
|
||||||
function_traits<CallbackT>::arity == 2
|
std::size_t Arity = 2
|
||||||
>::type * = nullptr,
|
|
||||||
typename std::enable_if<
|
|
||||||
std::is_same<
|
|
||||||
typename function_traits<CallbackT>::template argument_type<0>,
|
|
||||||
typename std::shared_ptr<MessageT>
|
|
||||||
>::value
|
|
||||||
>::type * = nullptr
|
|
||||||
>
|
>
|
||||||
void set(CallbackT callback)
|
typename std::enable_if<rclcpp::arity_comparator<Arity, CallbackT>::value, void>::type
|
||||||
{
|
set(
|
||||||
static_assert(std::is_same<
|
CallbackT callback,
|
||||||
|
typename std::enable_if<
|
||||||
|
std::is_same<
|
||||||
|
typename function_traits<CallbackT>::template argument_type<0>,
|
||||||
|
typename std::shared_ptr<MessageT>
|
||||||
|
>::value
|
||||||
|
>::type * = nullptr,
|
||||||
|
typename std::enable_if<
|
||||||
|
std::is_same<
|
||||||
typename function_traits<CallbackT>::template argument_type<1>,
|
typename function_traits<CallbackT>::template argument_type<1>,
|
||||||
const rmw_message_info_t &>::value,
|
const rmw_message_info_t &
|
||||||
"Passed incorrect argument type to callback, should be rmw_message_info_t");
|
>::value
|
||||||
|
>::type * = nullptr)
|
||||||
|
{
|
||||||
shared_ptr_with_info_callback = callback;
|
shared_ptr_with_info_callback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename CallbackT,
|
template<
|
||||||
typename std::enable_if<
|
typename CallbackT,
|
||||||
function_traits<CallbackT>::arity == 1
|
std::size_t Arity = 1
|
||||||
>::type * = nullptr,
|
|
||||||
typename std::enable_if<
|
|
||||||
std::is_same<
|
|
||||||
typename function_traits<CallbackT>::template argument_type<0>,
|
|
||||||
typename std::shared_ptr<const MessageT>
|
|
||||||
>::value
|
|
||||||
>::type * = nullptr
|
|
||||||
>
|
>
|
||||||
void set(CallbackT callback)
|
typename std::enable_if<rclcpp::arity_comparator<Arity, CallbackT>::value, void>::type
|
||||||
|
set(
|
||||||
|
CallbackT callback,
|
||||||
|
typename std::enable_if<
|
||||||
|
std::is_same<
|
||||||
|
typename function_traits<CallbackT>::template argument_type<0>,
|
||||||
|
typename std::shared_ptr<const MessageT>
|
||||||
|
>::value
|
||||||
|
>::type * = nullptr)
|
||||||
{
|
{
|
||||||
const_shared_ptr_callback = callback;
|
const_shared_ptr_callback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename CallbackT,
|
template<
|
||||||
typename std::enable_if<
|
typename CallbackT,
|
||||||
function_traits<CallbackT>::arity == 2
|
std::size_t Arity = 2
|
||||||
>::type * = nullptr,
|
|
||||||
typename std::enable_if<
|
|
||||||
std::is_same<
|
|
||||||
typename function_traits<CallbackT>::template argument_type<0>,
|
|
||||||
typename std::shared_ptr<const MessageT>
|
|
||||||
>::value
|
|
||||||
>::type * = nullptr
|
|
||||||
>
|
>
|
||||||
void set(CallbackT callback)
|
typename std::enable_if<rclcpp::arity_comparator<Arity, CallbackT>::value, void>::type
|
||||||
{
|
set(
|
||||||
static_assert(std::is_same<
|
CallbackT callback,
|
||||||
|
typename std::enable_if<
|
||||||
|
std::is_same<
|
||||||
|
typename function_traits<CallbackT>::template argument_type<0>,
|
||||||
|
typename std::shared_ptr<const MessageT>
|
||||||
|
>::value
|
||||||
|
>::type * = nullptr,
|
||||||
|
typename std::enable_if<
|
||||||
|
std::is_same<
|
||||||
typename function_traits<CallbackT>::template argument_type<1>,
|
typename function_traits<CallbackT>::template argument_type<1>,
|
||||||
const rmw_message_info_t &>::value,
|
const rmw_message_info_t &
|
||||||
"Passed incorrect argument type to callback, should be rmw_message_info_t");
|
>::value
|
||||||
|
>::type * = nullptr)
|
||||||
|
{
|
||||||
const_shared_ptr_with_info_callback = callback;
|
const_shared_ptr_with_info_callback = callback;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -25,6 +25,7 @@ namespace rclcpp
|
||||||
* but unfortunately std::function's constructor on VS2015 is too greedy,
|
* but unfortunately std::function's constructor on VS2015 is too greedy,
|
||||||
* so we need a mechanism for checking the arity and the type of each argument
|
* so we need a mechanism for checking the arity and the type of each argument
|
||||||
* in a callback function.
|
* in a callback function.
|
||||||
|
* See http://blogs.msdn.com/b/vcblog/archive/2015/06/19/c-11-14-17-features-in-vs-2015-rtm.aspx
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,6 +59,16 @@ struct function_traits<ReturnTypeT (ClassT::*)(Args ...) const>
|
||||||
: public function_traits<ReturnTypeT(ClassT &, Args ...)>
|
: public function_traits<ReturnTypeT(ClassT &, Args ...)>
|
||||||
{};
|
{};
|
||||||
|
|
||||||
|
/* NOTE(esteve):
|
||||||
|
* VS2015 does not support expression SFINAE, so we're using this template to evaluate
|
||||||
|
* the arity of a function.
|
||||||
|
*/
|
||||||
|
template<std::size_t Arity, typename FunctorT>
|
||||||
|
struct arity_comparator
|
||||||
|
{
|
||||||
|
static constexpr bool value = (Arity == function_traits<FunctorT>::arity);
|
||||||
|
};
|
||||||
|
|
||||||
} /* namespace rclcpp */
|
} /* namespace rclcpp */
|
||||||
|
|
||||||
#endif /* RCLCPP_RCLCPP_FUNCTION_TRAITS_HPP_ */
|
#endif /* RCLCPP_RCLCPP_FUNCTION_TRAITS_HPP_ */
|
||||||
|
|
|
@ -247,12 +247,30 @@ private:
|
||||||
bool ignore_local_publications,
|
bool ignore_local_publications,
|
||||||
typename message_memory_strategy::MessageMemoryStrategy<MessageT>::SharedPtr msg_mem_strat);
|
typename message_memory_strategy::MessageMemoryStrategy<MessageT>::SharedPtr msg_mem_strat);
|
||||||
|
|
||||||
|
/* NOTE(esteve):
|
||||||
|
* The following template machinery works around VS2015's lack of support for expression SFINAE:
|
||||||
|
* - We first declare the arity we want to match, i.e. 2 or 3.
|
||||||
|
* - Then we use the arity_comparator template to SFINAE on the arity of the passed functor.
|
||||||
|
* - Lastly, we SFINAE on the types of the arguments of the functor.
|
||||||
|
* These steps happen in different parts of the function signature because we want to stagger
|
||||||
|
* instantation of the templates because VS2015 can't conditionally enable templates that depend
|
||||||
|
* on another template.
|
||||||
|
* See test_function_traits.cpp for streamlined examples of how to use this pattern.
|
||||||
|
*/
|
||||||
template<
|
template<
|
||||||
typename ServiceT,
|
typename ServiceT,
|
||||||
typename FunctorT,
|
typename FunctorT,
|
||||||
typename std::enable_if<
|
std::size_t Arity = 2
|
||||||
function_traits<FunctorT>::arity == 2
|
>
|
||||||
>::type * = nullptr,
|
typename std::enable_if<
|
||||||
|
rclcpp::arity_comparator<Arity, FunctorT>::value,
|
||||||
|
typename rclcpp::service::Service<ServiceT>::SharedPtr
|
||||||
|
>::type
|
||||||
|
create_service_internal(
|
||||||
|
std::shared_ptr<rmw_node_t> node_handle,
|
||||||
|
rmw_service_t * service_handle,
|
||||||
|
const std::string & service_name,
|
||||||
|
FunctorT callback,
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
std::is_same<
|
std::is_same<
|
||||||
typename function_traits<FunctorT>::template argument_type<0>,
|
typename function_traits<FunctorT>::template argument_type<0>,
|
||||||
|
@ -264,14 +282,7 @@ private:
|
||||||
typename function_traits<FunctorT>::template argument_type<1>,
|
typename function_traits<FunctorT>::template argument_type<1>,
|
||||||
typename std::shared_ptr<typename ServiceT::Response>
|
typename std::shared_ptr<typename ServiceT::Response>
|
||||||
>::value
|
>::value
|
||||||
>::type * = nullptr
|
>::type * = nullptr)
|
||||||
>
|
|
||||||
typename rclcpp::service::Service<ServiceT>::SharedPtr
|
|
||||||
create_service_internal(
|
|
||||||
std::shared_ptr<rmw_node_t> node_handle,
|
|
||||||
rmw_service_t * service_handle,
|
|
||||||
const std::string & service_name,
|
|
||||||
FunctorT callback)
|
|
||||||
{
|
{
|
||||||
typename rclcpp::service::Service<ServiceT>::CallbackType callback_without_header =
|
typename rclcpp::service::Service<ServiceT>::CallbackType callback_without_header =
|
||||||
callback;
|
callback;
|
||||||
|
@ -282,9 +293,17 @@ private:
|
||||||
template<
|
template<
|
||||||
typename ServiceT,
|
typename ServiceT,
|
||||||
typename FunctorT,
|
typename FunctorT,
|
||||||
typename std::enable_if<
|
std::size_t Arity = 3
|
||||||
function_traits<FunctorT>::arity == 3
|
>
|
||||||
>::type * = nullptr,
|
typename std::enable_if<
|
||||||
|
arity_comparator<Arity, FunctorT>::value,
|
||||||
|
typename rclcpp::service::Service<ServiceT>::SharedPtr
|
||||||
|
>::type
|
||||||
|
create_service_internal(
|
||||||
|
std::shared_ptr<rmw_node_t> node_handle,
|
||||||
|
rmw_service_t * service_handle,
|
||||||
|
const std::string & service_name,
|
||||||
|
FunctorT callback,
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
std::is_same<
|
std::is_same<
|
||||||
typename function_traits<FunctorT>::template argument_type<0>,
|
typename function_traits<FunctorT>::template argument_type<0>,
|
||||||
|
@ -296,35 +315,14 @@ private:
|
||||||
typename function_traits<FunctorT>::template argument_type<1>,
|
typename function_traits<FunctorT>::template argument_type<1>,
|
||||||
typename std::shared_ptr<typename ServiceT::Request>
|
typename std::shared_ptr<typename ServiceT::Request>
|
||||||
>::value
|
>::value
|
||||||
>::type * = nullptr
|
>::type * = nullptr,
|
||||||
/*
|
|
||||||
TODO(esteve): reenable this block of code when VS2015 gets better support
|
|
||||||
for SFINAE and remove the static_assert from the body of this method. For
|
|
||||||
more info about the current support for SFINAE in VS2015 RC:
|
|
||||||
|
|
||||||
http://blogs.msdn.com/b/vcblog/archive/2015/04/29/c-11-14-17-features-in-vs-2015-rc.aspx
|
|
||||||
,
|
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
std::is_same<
|
std::is_same<
|
||||||
typename function_traits<FunctorT>::template argument_type<2>,
|
typename function_traits<FunctorT>::template argument_type<2>,
|
||||||
typename std::shared_ptr<typename ServiceT::Response>
|
typename std::shared_ptr<typename ServiceT::Response>
|
||||||
>::value
|
>::value
|
||||||
>::type * = nullptr
|
>::type * = nullptr)
|
||||||
*/
|
|
||||||
>
|
|
||||||
typename rclcpp::service::Service<ServiceT>::SharedPtr
|
|
||||||
create_service_internal(
|
|
||||||
std::shared_ptr<rmw_node_t> node_handle,
|
|
||||||
rmw_service_t * service_handle,
|
|
||||||
const std::string & service_name,
|
|
||||||
FunctorT callback)
|
|
||||||
{
|
{
|
||||||
static_assert(
|
|
||||||
std::is_same<
|
|
||||||
typename function_traits<FunctorT>::template argument_type<2>,
|
|
||||||
typename std::shared_ptr<typename ServiceT::Response>
|
|
||||||
>::value, "Third argument must be of type std::shared_ptr<ServiceT::Response>");
|
|
||||||
|
|
||||||
typename rclcpp::service::Service<ServiceT>::CallbackWithHeaderType callback_with_header =
|
typename rclcpp::service::Service<ServiceT>::CallbackWithHeaderType callback_with_header =
|
||||||
callback;
|
callback;
|
||||||
return service::Service<ServiceT>::make_shared(
|
return service::Service<ServiceT>::make_shared(
|
||||||
|
|
328
rclcpp/test/test_function_traits.cpp
Normal file
328
rclcpp/test/test_function_traits.cpp
Normal file
|
@ -0,0 +1,328 @@
|
||||||
|
// Copyright 2015 Open Source Robotics Foundation, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <rclcpp/function_traits.hpp>
|
||||||
|
|
||||||
|
int func_no_args()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int func_one_int(int)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int func_two_ints(int, int)
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int func_one_int_one_char(int, char)
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FunctionObjectNoArgs
|
||||||
|
{
|
||||||
|
int operator()() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FunctionObjectOneInt
|
||||||
|
{
|
||||||
|
int operator()(int) const
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FunctionObjectTwoInts
|
||||||
|
{
|
||||||
|
int operator()(int, int) const
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FunctionObjectOneIntOneChar
|
||||||
|
{
|
||||||
|
int operator()(int, char) const
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename FunctorT,
|
||||||
|
std::size_t Arity = 1
|
||||||
|
>
|
||||||
|
typename std::enable_if<rclcpp::arity_comparator<Arity, FunctorT>::value, int>::type
|
||||||
|
func_accept_callback(FunctorT callback,
|
||||||
|
typename std::enable_if<
|
||||||
|
std::is_same<
|
||||||
|
int,
|
||||||
|
typename rclcpp::function_traits<FunctorT>::template argument_type<0>
|
||||||
|
>::value
|
||||||
|
>::type * = nullptr
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int a = 4;
|
||||||
|
return callback(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename FunctorT,
|
||||||
|
std::size_t Arity = 2
|
||||||
|
>
|
||||||
|
typename std::enable_if<rclcpp::arity_comparator<Arity, FunctorT>::value, int>::type
|
||||||
|
func_accept_callback(FunctorT callback,
|
||||||
|
typename std::enable_if<
|
||||||
|
std::is_same<
|
||||||
|
int,
|
||||||
|
typename rclcpp::function_traits<FunctorT>::template argument_type<0>
|
||||||
|
>::value
|
||||||
|
>::type * = nullptr,
|
||||||
|
typename std::enable_if<
|
||||||
|
std::is_same<
|
||||||
|
int,
|
||||||
|
typename rclcpp::function_traits<FunctorT>::template argument_type<1>
|
||||||
|
>::value
|
||||||
|
>::type * = nullptr)
|
||||||
|
{
|
||||||
|
int a = 5;
|
||||||
|
int b = 6;
|
||||||
|
return callback(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename FunctorT,
|
||||||
|
std::size_t Arity = 2
|
||||||
|
>
|
||||||
|
typename std::enable_if<rclcpp::arity_comparator<Arity, FunctorT>::value, int>::type
|
||||||
|
func_accept_callback(FunctorT callback,
|
||||||
|
typename std::enable_if<
|
||||||
|
std::is_same<
|
||||||
|
int,
|
||||||
|
typename rclcpp::function_traits<FunctorT>::template argument_type<0>
|
||||||
|
>::value
|
||||||
|
>::type * = nullptr,
|
||||||
|
typename std::enable_if<
|
||||||
|
std::is_same<
|
||||||
|
char,
|
||||||
|
typename rclcpp::function_traits<FunctorT>::template argument_type<1>
|
||||||
|
>::value
|
||||||
|
>::type * = nullptr)
|
||||||
|
{
|
||||||
|
int a = 7;
|
||||||
|
char b = 8;
|
||||||
|
return callback(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Tests that funcion_traits calculates arity of several functors.
|
||||||
|
*/
|
||||||
|
TEST(TestFunctionTraits, arity) {
|
||||||
|
// Test regular functions
|
||||||
|
static_assert(
|
||||||
|
rclcpp::function_traits<decltype(func_no_args)>::arity == 0,
|
||||||
|
"Functor does not accept arguments");
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
rclcpp::function_traits<decltype(func_one_int)>::arity == 1,
|
||||||
|
"Functor only accepts one argument");
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
rclcpp::function_traits<decltype(func_two_ints)>::arity == 2,
|
||||||
|
"Functor only accepts two arguments");
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
rclcpp::function_traits<decltype(func_one_int_one_char)>::arity == 2,
|
||||||
|
"Functor only accepts two arguments");
|
||||||
|
|
||||||
|
// Test lambdas
|
||||||
|
auto lambda_no_args = []() {
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto lambda_one_int = [](int) {
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto lambda_two_ints = [](int, int) {
|
||||||
|
return 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto lambda_one_int_one_char = [](int, char) {
|
||||||
|
return 3;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
rclcpp::function_traits<decltype(lambda_no_args)>::arity == 0,
|
||||||
|
"Functor does not accept arguments");
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
rclcpp::function_traits<decltype(lambda_one_int)>::arity == 1,
|
||||||
|
"Functor only accepts one argument");
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
rclcpp::function_traits<decltype(lambda_two_ints)>::arity == 2,
|
||||||
|
"Functor only accepts two arguments");
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
rclcpp::function_traits<decltype(lambda_one_int_one_char)>::arity == 2,
|
||||||
|
"Functor only accepts two arguments");
|
||||||
|
|
||||||
|
// Test objects that have a call operator
|
||||||
|
static_assert(
|
||||||
|
rclcpp::function_traits<FunctionObjectNoArgs>::arity == 0,
|
||||||
|
"Functor does not accept arguments");
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
rclcpp::function_traits<FunctionObjectOneInt>::arity == 1,
|
||||||
|
"Functor only accepts one argument");
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
rclcpp::function_traits<FunctionObjectTwoInts>::arity == 2,
|
||||||
|
"Functor only accepts two arguments");
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
rclcpp::function_traits<FunctionObjectOneIntOneChar>::arity == 2,
|
||||||
|
"Functor only accepts two arguments");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Tests that funcion_traits deducts the type of the arguments of several functors.
|
||||||
|
*/
|
||||||
|
TEST(TestFunctionTraits, argument_types) {
|
||||||
|
// Test regular functions
|
||||||
|
static_assert(
|
||||||
|
std::is_same<
|
||||||
|
int,
|
||||||
|
rclcpp::function_traits<decltype(func_one_int)>::template argument_type<0>
|
||||||
|
>::value, "Functor accepts an int as first argument");
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
std::is_same<
|
||||||
|
int,
|
||||||
|
rclcpp::function_traits<decltype(func_two_ints)>::template argument_type<0>
|
||||||
|
>::value, "Functor accepts an int as first argument");
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
std::is_same<
|
||||||
|
int,
|
||||||
|
rclcpp::function_traits<decltype(func_two_ints)>::template argument_type<1>
|
||||||
|
>::value, "Functor accepts an int as second argument");
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
std::is_same<
|
||||||
|
int,
|
||||||
|
rclcpp::function_traits<decltype(func_one_int_one_char)>::template argument_type<0>
|
||||||
|
>::value, "Functor accepts an int as first argument");
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
std::is_same<
|
||||||
|
char,
|
||||||
|
rclcpp::function_traits<decltype(func_one_int_one_char)>::template argument_type<1>
|
||||||
|
>::value, "Functor accepts a char as second argument");
|
||||||
|
|
||||||
|
// Test lambdas
|
||||||
|
auto lambda_one_int = [](int) {
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto lambda_two_ints = [](int, int) {
|
||||||
|
return 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto lambda_one_int_one_char = [](int, char) {
|
||||||
|
return 3;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
std::is_same<
|
||||||
|
int,
|
||||||
|
rclcpp::function_traits<decltype(lambda_one_int)>::template argument_type<0>
|
||||||
|
>::value, "Functor accepts an int as first argument");
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
std::is_same<
|
||||||
|
int,
|
||||||
|
rclcpp::function_traits<decltype(lambda_two_ints)>::template argument_type<0>
|
||||||
|
>::value, "Functor accepts an int as first argument");
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
std::is_same<
|
||||||
|
int,
|
||||||
|
rclcpp::function_traits<decltype(lambda_two_ints)>::template argument_type<1>
|
||||||
|
>::value, "Functor accepts an int as second argument");
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
std::is_same<
|
||||||
|
int,
|
||||||
|
rclcpp::function_traits<decltype(lambda_one_int_one_char)>::template argument_type<0>
|
||||||
|
>::value, "Functor accepts an int as first argument");
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
std::is_same<
|
||||||
|
char,
|
||||||
|
rclcpp::function_traits<decltype(lambda_one_int_one_char)>::template argument_type<1>
|
||||||
|
>::value, "Functor accepts a char as second argument");
|
||||||
|
|
||||||
|
// Test objects that have a call operator
|
||||||
|
static_assert(
|
||||||
|
std::is_same<
|
||||||
|
int,
|
||||||
|
rclcpp::function_traits<FunctionObjectOneInt>::template argument_type<0>
|
||||||
|
>::value, "Functor accepts an int as first argument");
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
std::is_same<
|
||||||
|
int,
|
||||||
|
rclcpp::function_traits<FunctionObjectTwoInts>::template argument_type<0>
|
||||||
|
>::value, "Functor accepts an int as first argument");
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
std::is_same<
|
||||||
|
int,
|
||||||
|
rclcpp::function_traits<FunctionObjectTwoInts>::template argument_type<1>
|
||||||
|
>::value, "Functor accepts an int as second argument");
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
std::is_same<
|
||||||
|
int,
|
||||||
|
rclcpp::function_traits<FunctionObjectOneIntOneChar>::template argument_type<0>
|
||||||
|
>::value, "Functor accepts an int as first argument");
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
std::is_same<
|
||||||
|
char,
|
||||||
|
rclcpp::function_traits<FunctionObjectOneIntOneChar>::template argument_type<1>
|
||||||
|
>::value, "Functor accepts a char as second argument");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Tests that functions are matched via SFINAE.
|
||||||
|
*/
|
||||||
|
TEST(TestFunctionTraits, sfinae_match) {
|
||||||
|
EXPECT_EQ(1, func_accept_callback(func_one_int));
|
||||||
|
|
||||||
|
EXPECT_EQ(2, func_accept_callback(func_two_ints));
|
||||||
|
|
||||||
|
EXPECT_EQ(3, func_accept_callback(func_one_int_one_char));
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue