Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 函数模板能否推断出容器';s值类型?_C++_Qt_Templates - Fatal编程技术网

C++ 函数模板能否推断出容器';s值类型?

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;

假设我定义了以下函数模板,如果指定的函数为该项返回true,则该模板将从给定集合中删除该项

模板
内部删除项(
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)
 ....