我尝试制作一个功能模板,从矢量中删除一个值,给出一个键:
template
<
typename Value,
typename Map,
typename Key
>
void RemoveValue(
Map& m,
const Key& k,
const Value& v,
std::function<bool(const Value&)> f)
{
auto it1 = m.find(k);
if (it1 == m.end())
{
return;
}
auto vs = it1->second;
auto it2 = std::find_if(vs.begin(), vs.end(), f);
if (it2 == vs.end())
{
return;
}
vs.erase(it2);
if (vs.empty())
{
m.erase(it1);
}
}
当我使用它时:
RemoveValue(entityToTags, &entity, tag, [&](const Tag& t){ return t == tag; });
使用:
const Entity& entity, const Tag& tag
std::map<const Entity*, std::vector<Tag>> entityToTags;
我必须指定Tag
,即RemoveValue<Tag>(entityToTags, &entity, tag, [&](const Tag& t){ return t == tag; });
才能成功编译。
我怎样才能明确指定<Tag>
,让编译器知道它?
我正在使用VS2012。
谢谢!
答案 0 :(得分:4)
您可以简单地使用f
任意类型,而不是将其强制转换为std::function
。它更有意义,因为它甚至可以提高效率,标准库可以做到这一点。所以改变这样的功能:
template
<
typename Value,
typename Map,
typename Key,
typename Functor
>
void RemoveValue(
Map& m,
const Key& k,
const Value& v,
Functor f)
{
auto it1 = m.find(k);
if (it1 == m.end())
{
return;
}
auto vs = it1->second;
auto it2 = std::find_if(vs.begin(), vs.end(), f);
if (it2 == vs.end())
{
return;
}
vs.erase(it2);
if (vs.empty())
{
m.erase(it1);
}
}
答案 1 :(得分:2)
您应该将错误消息添加到您的问题中......
无论如何,我用CLang ++编译它,错误是:
test.cpp:47:5: error: no matching function for call to 'RemoveValue'
RemoveValue(entityToTags, &entity, tag, [&](const Tag &t) { return t == tag; });
^~~~~~~~~~~
test.cpp:15:6: note: candidate template ignored: could not match 'function<bool (const type-parameter-0-0 &)>' against '<lambda at t.cpp:47:45>'
void RemoveValue(
也就是说,要推断Tag
的类型,编译器必须使用第3个参数tag
和第4个参数。最后一个是std::function<bool(const Value&)>
类型,但是你传递一个lambda。是的,lambda可以转换为该类型,但不那个类型,因此Tag
的自动扣除失败。
解决方案是传递真实类型std::function<bool(const Value&)>
的值:
std::function<bool(const Tag&)> f = [&](const Tag &t) { return &t == &tag; };
RemoveValue(entityToTags, &entity, tag, f);
如果您愿意,可以使用static_cast<>()
,但我会发现该行太长了。