【发布时间】:2016-06-20 23:43:01
【问题描述】:
鉴于detection idiom 的(简化)实现
namespace type_traits
{
template<typename... Ts>
using void_t = void;
namespace detail
{
template<typename, template<typename...> class, typename...>
struct is_detected : std::false_type {};
template<template<class...> class Operation, typename... Arguments>
struct is_detected<void_t<Operation<Arguments...>>, Operation, Arguments...> : std::true_type {};
}
template<template<class...> class Operation, typename... Arguments>
using is_detected = detail::is_detected<void_t<>, Operation, Arguments...>;
template<template<class...> class Operation, typename... Arguments>
constexpr bool is_detected_v = detail::is_detected<void_t<>, Operation, Arguments...>::value;
}
我们可以很容易地检查一个类foo是否包含一个成员函数bar
struct foo {
int const& bar(int&&) { return 0; }
};
template<class T>
using bar_t = decltype(std::declval<T>().bar(0));
int main()
{
static_assert(type_traits::is_detected_v<bar_t, foo>, "not detected");
return 0;
}
但是,如您所见,我们无法检测到foo::bar 的参数类型是int&&。检测成功,因为0 可以传递给foo::bar。我知道有很多选项可以检查(成员)函数的 exact 签名。但是我想知道,是否可以修改这个检测工具包以检测foo::bar的参数类型恰好是int&&。
[我已经为这个例子创建了一个live demo。]
【问题讨论】:
-
如果唯一未知的部分是返回类型,这很简单。您是否还想涵盖多个参数,而您只想精确指定一些参数?那么成员函数的 cv 和 ref 限定符呢?
-
@dyp 目前,
is_detected_v<bar_t, T>将检测T是否有any 成员函数bar,它接受int。第一步,我想添加某种is_detected_exact来检测T是否有一个成员函数bar,其参数类型是exactlyint或exactlyint&&或 exactlyint const&等。在第二步中,我也想验证一个确切的返回类型,但我想这很容易,因为bar_t正是返回类型(只要decltype(...)中的表达式格式正确)。 -
@dyp 是的,像这样!我们可以用
functional标头的某些实用程序替换bar_helper吗? -
好吧,对于我的解决方案,您至少需要对返回类型进行类型推导。我不知道
<functional>中有任何此类工具。
标签: c++ templates c++14 sfinae typetraits