English 中文(简体)
为什么模版的推论因下列因素而致残:
原标题:Why is template argument deduction disabled with std::forward?

在VS2010年,以下定义是:

template<class _Ty> inline
_Ty&& forward(typename identity<_Ty>::type& _Arg)
{   // forward _Arg, given explicitly specified type parameter
    return ((_Ty&&)_Arg);
}

<代码>识别度似乎仅用于可辨率的模板论证扣减。 在本案中,什么是故意 dis弃?

最佳回答

如果您对一个类型标的X的标注作一个模版功能,即<代码>。 T&&,作为其参数,模板论据扣除duces <代码>T至X。 因此,参数为<代码>X&&。 如果职能论证是价值或最轻价值,则汇编者将其类型推断为价值参考或该类中值参考。

www.un.org/Depts/DGACM/index_spanish.htm 如std:forward 使用的模板论点扣减:

自<代码>标有名称的物体为 唯一时间:<代码> 将正确列入<代码> T&&系指输入论点为无名的超值时(如7func()。 如欲完善<代码>arg,请通过<代码>std:forward,因其名称而是一种价值。 <代码>std:forwards, 类型将作为价值参考或参考。 参考编码将产生<代码>。 T&&,载于static_cast<T&&>(arg) in :forward to persistent resolution as an l Value reference or const l Value reference.

<>>Example:

template<typename T>
T&& forward_with_deduction(T&& obj)
{
    return static_cast<T&&>(obj);
}

void test(int&){}
void test(const int&){}
void test(int&&){}

template<typename T>
void perfect_forwarder(T&& obj)
{
    test(forward_with_deduction(obj));
}

int main()
{
    int x;
    const int& y(x);
    int&& z = std::move(x);

    test(forward_with_deduction(7));    //  7 is an int&&, correctly calls test(int&&)
    test(forward_with_deduction(z));    //  z is treated as an int&, calls test(int&)

    //  All the below call test(int&) or test(const int&) because in perfect_forwarder  obj  is treated as
    //  an int& or const int& (because it is named) so T in forward_with_deduction is deduced as int& 
    //  or const int&. The T&& in static_cast<T&&>(obj) then collapses to int& or const int& - which is not what 
    //  we want in the bottom two cases.
    perfect_forwarder(x);           
    perfect_forwarder(y);           
    perfect_forwarder(std::move(x));
    perfect_forwarder(std::move(y));
}
问题回答

由于<代码>std:forward(expr)不适用。 它所能做的唯一事情是一站不住脚的,即它的论点完美无缺,并像身份功能。 另一种选择是,它与<代码>std:move相同,但我们already有这种区别。 换言之,假定有可能,

template<typename Arg>
void generic_program(Arg&& arg)
{
    std::forward(arg);
}

<代码>std:forward(arg) is semantically Equal to arg。 另一方面,<代码>std:forward<Arg>(arg)在一般情况下不是一例。

因此,通过禁止<代码>std:forward(arg),它有助于捕获方案错误,而且由于对<代码>的任何可能使用,我们没有任何损失:forward(arg)被“arg三字取代。


我认为,如果我们侧重于什么确切的<代码>:forward<Arg>arg) <>>>>m>does<>em>,而不是std:forward(arg) do(因为它不关心任何选择)。 让我们努力撰写一份完全推进其论点的“禁用功能模板”。

template<typename NoopArg>
NoopArg&& noop(NoopArg&& arg)
{ return arg; }

这种阴险的首次尝试相当有效。 如果我们打电话noop(0),则NoopArg改为int<>。 这意味着,回归类型为<代码>int&&,而且我们可以从<代码>arg上对这种高价值参照加以约束,该表述为“价值”(即参数名称)。 如果我们这样做的话:

template<typename NoopArg>
NoopArg&& noop(NoopArg&& arg)
{ return std::move(arg); }

然后int i = 0; noop(i);失败。 此时此刻,NoopArg被引为int&(参引规则保障int&& 倒至int&,因此回归类型为int&;,此时此刻,我们可以从

在像<代码>noop这样的完美功能方面,有时<>> 我们希望采取行动,但其他时候我们不这样做。 了解我们是否应移动的规则取决于。 Arg:如果它不是低值参考类型,它就是指<代码>noop被超值通过。 如果是一升值参考类型,则指noop的升值。 因此,在<代码>td:forward<NoopArg>arg)上,NoopArg 必要的论据至std:forward,以便该功能模板做正确的事情。 没有这种信息,就没有足够的信息。 www.un.org/Depts/DGACM/index_french.htm 将在一般情况下推断。

www.un.org/Depts/DGACM/index_spanish.htm 简短回答:

由于<<>代码>:forward to work as inook(即:既通过原有的类型信息),meant to beed>>;strong>>.enclosing model context/strong,

虽然使用<代码>std:在非典型情况下,可以采用<<>tong>(详见下文)。

And if anyone dares to try implementing std::forward to allow type deducing, he/she is doomed to fail painfully.

<>Details:

例:

template <typename T>
auto someFunc(T&& arg){ doSomething(); call_other_func(std::forward<T>(para)); }

观察员<代码>arg

Thanks to universal reference, some type deduce magic happens when someFunc is being instantiated, specifically as following:

  • If an rvalue object, which has the type _T or _T &, is passed to someFunc, T will be deduced as _T &(, yeah, even if the type of X is just _T, please read Meyers artical);
  • If an rvalue of type _T && is passed to someFuncT will be deduced as _T &&

现在,你可以将<代码>T改为上述代码中的真实类型:

当高压肥料通过时:

auto someFunc(_T & && arg){ doSomething(); call_other_func(std::forward<_T &>(arg)); }

And after applying reference collapse rule(, pls read Meyers artical), we get:

auto someFunc(_T & arg){ doSomething(); call_other_func(std::forward<_T &>(arg)); }

当高价值切除时:

auto someFunc(_T && && arg){ doSomething(); call_other_func(std::forward<_T &&>(arg)); }

在适用参考崩溃规则(插头改为

auto someFunc(_T && arg){ doSomething(); call_other_func(std::forward<_T &&>(arg)); }

现在,你可以猜测:按字母顺序排列的只是static_cast<T>(第(事实上,在)。 11个版本是static_cast< T &&> (para), 这与应用参考串通规则相同。 一切都做的是罚款。

但是,如果你想 let:fowrd deducing the category param by se, 就会很快发现,inside someFunc,>>:forwardlichly:IS NOT ABLE to deduce the original category of arg

如果您试图使汇编者能够做到这一点,则将永远作为加以翻译。&&(, 是的,甚至 ,arg

Last, why should you only use std::forward inside templates? Because in non-templates context, you know exactly what type of obj you have. So, if you have an lvalue bind to an rvalue reference, and you need to pass it as an lvaule to another function, just pass it, or if you need to pass it as rvalue, just do std::move. You simply DON T NEED std::forward inside non-template context.





相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?