C++ 函数模板能否推断出容器';s值类型?
假设我定义了以下函数模板,如果指定的函数为该项返回true,则该模板将从给定集合中删除该项C++ 函数模板能否推断出容器';s值类型?,c++,qt,templates,C++,Qt,Templates,假设我定义了以下函数模板,如果指定的函数为该项返回true,则该模板将从给定集合中删除该项 模板 内部删除项( QSet&set, const std::function&shouldRemove) { int numRemoved=0; auto iter=set.begin(); while(iter!=set.end()) { 如果(应移除(*iter)) { iter=设置擦除(iter); ++numRemoved; } 其他的 { ++iter; } } 返回numRemoved;
模板
内部删除项(
QSet&set,
const std::function&shouldRemove)
{
int numRemoved=0;
auto iter=set.begin();
while(iter!=set.end())
{
如果(应移除(*iter))
{
iter=设置擦除(iter);
++numRemoved;
}
其他的
{
++iter;
}
}
返回numRemoved;
}
我可以像这样使用此函数模板:
template<typename T>
struct do_not_deduce
{
using type = T;
};
template<typename T>
using do_not_deduce_t = typename do_not_deduce<T>::type;
template<typename TYPE>
int removeItems(
QSet<TYPE>& set,
const std::function<bool (const do_not_deduce_t<TYPE>&)>& shouldRemove)
....
QSet-stuff={“A”、“A”、“B”、“B”、“C”、“C”};
移除项(填充物,[](常量QString&thing){
return thing.toLower()=“a”;
});
qDebug()如果您可以容忍稍微激进的duck类型,那么在容器本身上创建模板,并在模板中提取值\u type
,您就可以做到这一点
template<typename ContainerT>
int removeItems(
ContainerT& set,
const std::function<bool (const typename ContainerT::value_type&)>& shouldRemove)
{
Edit作为参考,值得注意的是,如果没有该std::function
参数,编译器将能够正确地推断类型。因此,以下方法也适用:
template<typename TYPE, typename CheckT>
int removeItems(
QSet<TYPE>& set,
const CheckT& shouldRemove)
{
模板
内部删除项(
QSet&set,
常量检查(应删除(&S)
{
std::function
会把事情搞砸,因为lambda需要隐式转换为std::function
,隐式转换不能很好地进行模板推理
value\u type
版本之所以有效,是因为std::function
的类型完全由第一个参数决定
- 具有duck类型回调的版本可以工作,因为lambda按原样使用,而无需进行隐式转换
您可以使用
template<typename SET>
int removeItems(
SET& set,
const std::function<bool (const typename SET::key_type&)>& shouldRemove);
是的,你绝对可以这样做。就像这样:
template<typename T>
struct do_not_deduce
{
using type = T;
};
template<typename T>
using do_not_deduce_t = typename do_not_deduce<T>::type;
template<typename TYPE>
int removeItems(
QSet<TYPE>& set,
const std::function<bool (const do_not_deduce_t<TYPE>&)>& shouldRemove)
....
模板
结构不推断
{
使用类型=T;
};
模板
使用do_not_Destruction_t=typename do_not_Destruction::type;
模板
内部删除项(
QSet&set,
const std::function&shouldRemove)
....
问题在于removitems
试图从两个输入推断类型。
因此,将lambda作为第二个参数传递会导致演绎出现问题,因为它需要转换为正确类型的std::function
,这在模板参数演绎过程中相当复杂
在我提供的解决方案中,我只是从第二个参数中删除了参数演绎,因此演绎只根据第一个参数进行,随后就成功了
注意:您不应该使用std::function
进行快速检查,因为它相当慢。
您最好接受一个常规模板参数,并通过SFINAE验证它是否可调用并且具有正确的签名。我最终使用了基于和的解决方案。前者提供的解决方案不仅仅处理QSet,而后者提供的解决方案总体上更简单
模板
int removeItems(容器和容器,Pred shouldRemove)
{
int numRemoved=0;
auto iter=container.begin();
while(iter!=container.end())
{
如果(应移除(*iter))
{
iter=容器擦除(iter);
++numRemoved;
}
其他的
{
++iter;
}
}
返回numRemoved;
}
我没有真正的对象,但您可以使用QObject基来接受,然后尝试使用动态强制转换在内部强制转换。我认为这可以通过模板模板来完成,例如模板移除项(容器和集,…{…}
这展示了如何为stl容器设置模板:,其中许多模板也可以很容易地应用于您的案例。imo的最佳解决方案是完全从签名中删除std::function
。以产生类型擦除的成本(更不用说对TAD的影响)在我的书中,仍然使用函数模板是一种悲观。只需添加一个模板参数Pred
,并将函数参数声明为Pred shouldRemove
。从那时起,一切都将正常工作(TM)(具有更好的内联)。
template<typename T>
struct do_not_deduce
{
using type = T;
};
template<typename T>
using do_not_deduce_t = typename do_not_deduce<T>::type;
template<typename TYPE>
int removeItems(
QSet<TYPE>& set,
const std::function<bool (const do_not_deduce_t<TYPE>&)>& shouldRemove)
....