在这样的代码中:
template<class...> struct pack{};
template<class, class = int>
struct call_t
{
template<class... args_t>
static int apply(args_t&&...)
{ return 0; }
};
template<class... args_t>
struct call_t<pack<args_t...>, // (1)
std::decay_t<decltype(convert(declval<args_t>()...))> >
{
template<class... params_t> // (2)
static int apply(params_t&&... args)
{ return convert(std::forward<params_t>(args)...); }
};
template<class... args_t>
auto test(args_t&&... args) // (3)
{
return call_t<pack<args_t...> >::
apply(std::forward<args_t>(args)...);
}
此函数根据函数是否convert
存在并将一组参数发送到一个函数或另一个函数,并且可以使用传递的参数调用,保持完整(我猜)它们的确切传递类型,以及当它的返回类型为 时int
,不管引用或 const限定词。
我对那段代码有三个疑问。
(1)
declval
返回类型仍然是通用引用吗?例如,declval<T>()
, withT = int&
, 它的返回类型是int&&
(一个真正的 r 值引用),还是在传递给另一个调用时int & &&
再次推导出为int&
遵循通用引用的通常规则?我认为它没有(正如@101010 所指出的),但我不知道在这种情况下如何进行完美的重载测试。(2)是否需要重新指定可变参数模板才能使用通用引用推导规则,或者由于(3)中已经推导出了正确的类型,所以它们保持推导的类型不变?
或者我可以写吗
template<class... args_t>
struct call_t<pack<args_t...>, // (1)
std::decay_t<decltype(convert(declval<args_t>()...))> >
{
// (2)
static int apply(args_t... args)
{ return convert(args...); }
};
?
模板类是一个实现细节,因此call_t
,它只会在内部实例化test
。