【发布时间】:2015-11-05 10:23:42
【问题描述】:
假设我有一些函数,一个参数类型(或几个参数类型),我想推导出它的类型。此外,我想要基于事实的不同行为是右值还是左值。由于完美的转发,直接写它会导致一个明显的(对于有经验的人)陷阱:
#include <iostream>
#include <vector>
template <typename T>
void f (T &&v) // thought to be rvalue version
{
// some behavior based on the fact that v is rvalue
auto p = std::move (v);
(void) p;
}
template <typename T>
void f (const T &v) // never called
{
auto p = v;
(void) p;
}
int main ()
{
std::vector<int> x = {252, 135};
auto &z = x;
f (z);
std::cout << x.size () << '\n'; // woah, unexpected 0 or crash
}
尽管这种行为的鬼鬼祟祟的性质已经是一个有趣的观点,但我的问题实际上是不同的——对于这种情况,什么是好的、简洁、易于理解的解决方法?
如果没有推断出完全转发的类型(例如,它是已知的外部类的模板参数或类似的东西),则使用typename identity<T>::type&& 而不是T&& 的解决方法是众所周知的,但由于相同的构造是避免类型的解决方法扣除在这种情况下没有帮助。我可能可以想象一些 sfinae 技巧来解决它,但代码清晰度可能会被破坏,并且它看起来与类似的非模板函数完全不同。
【问题讨论】:
-
什么崩溃?
size没有前置条件,因此可以在移动的向量上调用。
标签: c++ c++11 move-semantics perfect-forwarding template-argument-deduction