Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/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++ Lambdas和std::function_C++_Templates_Lambda_C++11 - Fatal编程技术网

C++ Lambdas和std::function

C++ Lambdas和std::function,c++,templates,lambda,c++11,C++,Templates,Lambda,C++11,我正在努力赶上C++11和所有伟大的新功能。我有点迷恋兰博达斯 以下是我能够开始工作的代码: #include <iostream> #include <cstdlib> #include <vector> #include <string> #include <functional> using namespace std; template<typename BaseT, typename Func> vector&

我正在努力赶上C++11和所有伟大的新功能。我有点迷恋兰博达斯

以下是我能够开始工作的代码:

#include <iostream>
#include <cstdlib>
#include <vector>
#include <string>
#include <functional>

using namespace std;

template<typename BaseT, typename Func>
vector<BaseT> findMatches(vector<BaseT> search, Func func)
{
    vector<BaseT> tmp;

    for(auto item : search)
    {
        if( func(item) )
        {
            tmp.push_back(item);
        }
    }

    return tmp;
}

void Lambdas()
{
    vector<int> testv = { 1, 2, 3, 4, 5, 6, 7 };

    auto result = findMatches(testv, [] (const int &x) { return x % 2 == 0; });

    for(auto i : result)
    {
        cout << i << endl;
    }
}

int main(int argc, char* argv[])
{

    Lambdas();

    return EXIT_SUCCESS;
}
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
模板
矢量搜索匹配(矢量搜索,Func Func)
{
向量tmp;
用于(自动项目:搜索)
{
if(职能(项目))
{
tmp.推回(项目);
}
}
返回tmp;
}
void Lambdas()
{
向量testv={1,2,3,4,5,6,7};
自动结果=findMatches(testv,[](const int&x){返回x%2==0;});
用于(自动i:结果)
{

CUT< P > Stephan T. Lavavej解释了为什么这不能起作用。基本上,问题是编译器试图从:STD::vector < /C> >和<代码> STD::函数参数。C++中的lambda不是类型:<代码> STD::函数< /C> >,它是一个未命名的、唯一的不可联合类型,可转换为函数指针,如果它没有捕获列表(空的
[]
)。另一方面,可以从任何可能类型的可调用实体(函数指针、成员函数指针、函数对象)创建
std::function
对象

请注意,我个人不明白为什么要将传入的functor限制为该特定签名(此外,通过多态函数包装器(如
std::function
)进行间接寻址比直接调用functor(甚至可能是内联的)效率要低得多),但这里有一个有效的版本。基本上,它在
std::function
部分禁用参数推断,并且仅从
std::vector
参数推断
BaseT

template<class T>
struct Identity{
  typedef T type;
};

template<typename BaseT>
vector<BaseT> findMatches(vector<BaseT> search, 
    typename Identity<function<bool (const BaseT &)>>::type func)
{
    vector<BaseT> tmp;

    for(auto item : search)
    {
        if( func(item) )
        {
            tmp.push_back(item);
        }
    }

    return tmp;
}
模板
结构标识{
T型;
};
模板
矢量搜索匹配(矢量搜索,
typename标识::type func)
{
向量tmp;
用于(自动项目:搜索)
{
if(职能(项目))
{
tmp.推回(项目);
}
}
返回tmp;
}

另一种可能的方法是不直接限制函子类型,而是通过SFINAE间接限制函子类型:

template<class T, class F>
auto f(std::vector<T> v, F fun)
    -> decltype(bool(fun(v[0])), void())
{
  // ...
}
模板
自动f(标准::向量v,f fun)
->decltype(bool(fun(v[0])),void())
{
// ...
}


如果
fun
不接受类型为
t&
的参数,或者如果返回类型不能转换为
bool
,则此函数将从重载集中删除。
,void()
makes
f
的返回类型
void

正如其他海报所揭示的,这是std::function的模板参数推导

使第二个代码段工作的一种直观方法是在调用模板函数时添加基本类型:
findMatches

Xeo未提及的另一种方法是使用std::is_可转换:

template<typename BaseT, typename FUNC>
vector<BaseT> findMatches(vector<BaseT> search, function <bool (const BaseT &)> func)
{
    static_assert(std::is_convertible<FUNC, function<bool (const BaseT &)> >::value, "func must be convertible to ...");

    vector<BaseT> tmp;

    for(auto item : search)
    {
        if( func(item) )
        {
            tmp.push_back(item);
        }
    }

    return tmp;
}
模板
矢量搜索匹配(矢量搜索,函数func)
{
静态断言(std::is_convertable::value,“func必须可转换为…”);
向量tmp;
用于(自动项目:搜索)
{
if(职能(项目))
{
tmp.推回(项目);
}
}
返回tmp;
}

它避免将lamda包装到std::function中,并提供更清晰的错误消息。

如果您想做什么(即使用
std::function
)您会遇到什么错误?也不是说GCC中不完全支持某些C++11支持,甚至GCC 4.7中也不完全支持,更不用说4.6了。您的第二个代码示例看起来不错;您会遇到什么错误?模板只允许精确匹配,因此您无法将lambda传递给需要
std::function
的函数模板。此外,
function
Constructor不需要拒绝实际上与
函数
签名不匹配的参数,因此缩小范围实际上并不有用。与您的问题无关,但由于您正在学习C++11功能,您应该查找。要创建测试向量,您只需执行
向量testv{1,2,3,4,5,6,7}
而不是使用连续的
push_back
s.@MSalters:是的,我的意思是不准确。模板参数推断就是我的意思。因此,为了澄清,OP的代码示例失败,因为编译器正试图对
std::function
参数进行模板参数推断?不需要
Identity
:只需使用
std::common_type::type
@KerrekSB:Meh,我认为这个答案更清楚,因为
Identity
的实现非常透明。还澄清了lambda转换部分。@Xeo:我不想阻止某些lamda传入,当向量为int类型时,这些lamda可能不会返回bool或将const ref传递给字符串。I bas不要像C#中的委托那样使用它,也许这是我的问题。@Mithrandir:C++的类型系统将为您处理这个问题,如果
fun
的返回类型不能转换为bool(它需要在
if
语句中使用),它将无法编译或者,如果
fun
不接受类型为
BaseT
的参数,则第二个代码,即SFINAE代码,只会给出更清晰的错误消息。
template<typename BaseT, typename FUNC>
vector<BaseT> findMatches(vector<BaseT> search, function <bool (const BaseT &)> func)
{
    static_assert(std::is_convertible<FUNC, function<bool (const BaseT &)> >::value, "func must be convertible to ...");

    vector<BaseT> tmp;

    for(auto item : search)
    {
        if( func(item) )
        {
            tmp.push_back(item);
        }
    }

    return tmp;
}