【发布时间】:2017-04-11 00:40:43
【问题描述】:
在这样的代码中:
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>()和T = 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 内部实例化。
【问题讨论】:
-
关于第一个问题:
std::decval的返回类型是T&&,除非T是(可能是 cv-qualified)void,在这种情况下返回类型是T。 -
所以我失去了(3)中传递参数的原始类型。问题是我不知道如何进行完美的“重载测试”(在未评估的上下文中),或者至少不涉及更多额外的辅助模板。
-
不,如果
T = int&例如,T&&确实是int&通过引用折叠规则 -
由于您的代码正在运行,我认为这是CodeReview的问题
-
@J.H.Bonarius 我不想表现得像个“巨魔”,在不同的地方发布相同的问题。我的问题有两种性质,如果它对任何
convert重载都能可靠地工作(我认为这个问题更接近于 StackOverflow,但我没有失败的用例),以及如果模板 (2) 是多余的(也许更多适合 CodeReview,因为我认为它不会影响预期目的的“语义”)。
标签: c++ templates c++14 forwarding-reference