在编译时告诉lambda(或函数对象)是否有默认参数的最简单方法是什么? 例如:
auto f = [](int i=0){};
auto g = [](int i){};
static_assert(has_default_arg<decltype(f)>::value==true);
static_assert(has_default_arg<decltype(g)>::value==false);
答案 0 :(得分:5)
我不相信没有某种功能静态反射就可以检测到这种情况。但是,您可以检查lambda是否可以使用零参数和一个参数进行调用。使用detection idiom的示例:
template <class T>
using invocable_zero = decltype(std::declval<T&>()());
template <class T, class X>
using invocable_one = decltype(std::declval<T&>()(std::declval<X>()));
template <class T, class X>
struct has_default_arg : std::conjunction<
std::experimental::is_detected<invocable_zero, T>,
std::experimental::is_detected<invocable_one, T, X>
> { };
答案 1 :(得分:1)
如NathanOliver中指出comment,您无法对普通函数对象执行此操作。所以我们只专注于lambda。
首先,我们可以创建一个帮助器类来检查是否可以使用从F
通过索引序列Args...
选择的参数调用Index_sequence
:
template <typename F, typename Index_sequence, typename... Args>
struct is_invocable_for_indices : std::false_type {};
template <typename F, size_t... Is, typename... Args>
struct is_invocable_for_indices<F, std::index_sequence<Is...>, Args...>
: std::is_invocable<F, std::tuple_element_t<Is, std::tuple<Args...>>...> {};
template <typename F, typename Index_sequence, typename... Args>
inline constexpr bool is_invocable_for_indices_v = is_invocable_for_indices<F, Index_sequence, Args...>::value;
// example use
auto f = [](int i = 0) {};
auto g = [](int i) {};
static_assert(is_invocable_for_indices_v<decltype(f), std::index_sequence<>, int>);
static_assert(!is_invocable_for_indices_v<decltype(g), std::index_sequence<>, int>);
static_assert(is_invocable_for_indices_v<decltype(g), std::index_sequence<0>, int>);
让Args
成为F
的参数类型,可以通过decltype(&F::operator())
检测到(这个想法来自this answer)。现在,您可以通过检查是否可以使用F
的{{1}}个参数调用F
来检查sizeof...(Args) - 1
是否具有默认参数。因此,我们可以按如下方式定义Args
:
has_defulat_arg