考虑这个简单的程序:
vector<int> foo = {0, 42, 0, 42, 0, 42};
replace(begin(foo), end(foo), foo.front(), 13);
for(const auto& i : foo) cout << i << '\t';
当我写这篇文章时,我希望得到:
13 42 13 42 13 42
但我得到了:
13 42 0 42 0 42
问题当然是replace
通过引用接收最后2个参数。因此,如果它们中的任何一个碰巧处于正在操作的范围内,结果可能是意外的。我可以通过添加临时变量来解决这个问题:
vector<int> foo = {0, 42, 0, 42, 0, 42};
const auto temp = foo.front();
replace(begin(foo), end(foo), temp, 13);
for(const auto& i : foo) cout << i << '\t';
我知道C ++ 11为我们提供了各种类型的工具,我可以简单地将这个值强制转换为非引用类型并传递内联,而不创建临时的吗?
答案 0 :(得分:9)
解决方案可以如下(即使你是临时的)
template<class T>
void replace_value_of_first(std::vector<T>& v, const T& value)
{
std::replace(v.begin(), v.end(), T(v.front()), value);
}
答案 1 :(得分:7)
您可以编写一个引用引用并返回值的简单函数。这将&#34;转换&#34;引用到一个值。这确实会生成一个临时的,但它是未命名的,并将在完整表达式的末尾销毁。像
这样的东西template<typename T>
T value(const T& ref)
{
return ref;
}
然后你可以像
一样使用它int main()
{
vector<int> foo = {0, 42, 0, 42, 0, 42};
replace(begin(foo), end(foo), value(foo.front()), 13);
for(const auto& i : foo) cout << i << '\t';
}
输出:
13 42 13 42 13 42
答案 2 :(得分:4)
您可以将给定值转换为rvalue
以达到预期效果。下面的示例可以在不定义任何额外函数的情况下工作,只需在值中加零即可。
vector<int> foo = {0, 42, 0, 42, 0, 42};
replace(begin(foo), end(foo), foo.front()+0, 13);
for(const auto& i : foo) cout << i << '\t';
甚至(正如Jarod42所建议的)只有一元+
运算符,这是一个无操作:
vector<int> foo = {0, 42, 0, 42, 0, 42};
replace(begin(foo), end(foo), +foo.front(), 13);
for(const auto& i : foo) cout << i << '\t';
显然,其中任何一个仍然会造成一个暂时的。我不认为你可以摆脱它。
答案 3 :(得分:1)
在此特定情况下(当旧值是向量的第一个时),您可以使用<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@class">
<xsl:attribute name="class">
<xsl:choose>
<xsl:when test=". = 'b1'">
<xsl:text>c1</xsl:text>
</xsl:when>
<xsl:when test=". = 'b2'">
<xsl:text>c2</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
和rbegin()
来反转替换顺序。
一般来说,我不知道是否有可能以简单的方式进行复制。
rend()
p.s:抱歉我的英语不好。
答案 4 :(得分:1)
答案 5 :(得分:1)
一个适用于任何类型的衬垫,不仅仅是数字:
replace(begin(foo), end(foo), make_pair(foo.front(),0).first, 13);
或不创建额外字段:
replace(begin(foo), end(foo), get<0>( make_tuple(foo.front()) ), 13);
答案 6 :(得分:1)
vector<int> foo = {0, 42, 0, 42, 0, 42};
replace(begin(foo), end(foo), static_cast<int>(foo.front()), 13);
assert(equal(begin(foo), end(foo), begin({13, 42, 13, 42, 13, 42})));