C++11 将可调用对象传递给构建某种多索引容器的对象

C++11 将可调用对象传递给构建某种多索引容器的对象,c++11,lambda,c++14,callable,generic-lambda,C++11,Lambda,C++14,Callable,Generic Lambda,我正在尝试编写一个容器,它能够对对象进行分类,并存储分类函数为true的指针 我的问题是,它没有编译,而且由于我对诸如std::function或lambdas之类的可调用项缺乏经验,我不确定如何修复它 我想要这样一个容器,因为我经常需要获取一些“类别”——这使得缓存结果变得很容易。特别是在本例中,如果狗更改其声音,则可以简单地重新创建类别(因为可调用项仍然存在) 更重要的是,我对提供良好性能的解决方案感兴趣。正如我读到的,std::functions不太可能是inlined。有没有一种方法可以

我正在尝试编写一个容器,它能够对对象进行分类,并存储分类函数为true的指针

我的问题是,它没有编译,而且由于我对诸如
std::function
lambdas
之类的可调用项缺乏经验,我不确定如何修复它

我想要这样一个容器,因为我经常需要获取一些“类别”——这使得缓存结果变得很容易。特别是在本例中,如果
狗更改其
声音
,则可以简单地重新创建类别(因为可调用项仍然存在)

更重要的是,我对提供良好性能的解决方案感兴趣。正如我读到的,
std::function
s不太可能是
inline
d。有没有一种方法可以提供
内联
d-performance

编者说:

main.cpp: In function 'int main()':
main.cpp:51:108: error: no matching function for call to 'CategoryContainer<Dog>::addCategory(CategoryContainer<Dog>::Categories, main()::<lambda(auto:1&)>)'
     dogs.addCategory( CategoryContainer<Dog>::Categories::Wuff, [](auto& d){return d.makeSound()=="Wuff";} );

main.cpp:39:10: note: candidate: void CategoryContainer<T>::addCategory(CategoryContainer<T>::Categories, std::function<bool()>) [with T = Dog]
     void addCategory(Categories cat, std::function<bool()> f) {
main.cpp:39:10: note:   no known conversion for argument 2 from 'main()::<lambda(auto:1&)>' to 'std::function<bool()>'

main.cpp: In lambda function:
main.cpp:52:71: error: expected '{' before '(' token
     dogs.addCategory( CategoryContainer<Dog>::Categories::WauWau, []()(auto& d){return d.makeSound()=="WauWau";} );

main.cpp: In function 'int main()':
main.cpp:52:72: error: expected primary-expression before 'auto'
     dogs.addCategory( CategoryContainer<Dog>::Categories::WauWau, []()(auto& d){return d.makeSound()=="WauWau";} );
main.cpp:在函数“int main()”中:
main.cpp:51:108:错误:调用“CategoryContainer::addCategory(CategoryContainer::Categories,main():)”时没有匹配的函数
addCategory(CategoryContainer::Categories::Wuff,[](auto&d){return d.makeSound()==“Wuff”;});
main.cpp:39:10:注:候选者:void CategoryContainer::addCategory(CategoryContainer::Categories,std::function)[with T=Dog]
void addCategory(类别类别,标准::函数f){
main.cpp:39:10:注意:参数2没有从“main()::”到“std::function”的已知转换
main.cpp:在lambda函数中:
main.cpp:52:71:错误:在“(”标记)之前应为“{”
dogs.addCategory(CategoryContainer::Categories::WauWau,[]()(auto&d){return d.makeSound()=“WauWau”;});
main.cpp:在函数“int main()”中:
main.cpp:52:72:错误:应在“auto”之前使用主表达式
dogs.addCategory(CategoryContainer::Categories::WauWau,[]()(auto&d){return d.makeSound()=“WauWau”;});
这是我的代码:

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

class Dog
{
public:
    std::string makeSound() { return _sound; }
    void setSound(std::string sound) { _sound=sound; }
private:
    std::string _sound = "Wuff";
};

template<class T>
class CategoryContainer
{
public:
    using objectContainer = std::vector<T>;
    using pointerContainer = std::vector<T*>;

    enum class Categories { Wuff, WauWau }; // Dogs are e.g. destinguished by the sound they make.

    struct Category {
        std::function<bool()> func;
        pointerContainer pointers;
        Category(std::function<bool()> f, objectContainer& data) : func(f) {
            for(auto& i : data)
                if( func(i) )
                    pointers.emplace_back(&i);
        }
    };

    CategoryContainer(size_t n) {
        data.resize(n); // Construct so many dogs.
    }

    void addCategory(Categories cat, std::function<bool()> f) {
        indexed[cat] = Category(f, data);
    }

private:
    objectContainer data;
    std::unordered_map<Categories, Category> indexed;
};

int main()
{
    CategoryContainer<Dog> dogs(10);
    dogs.addCategory( CategoryContainer<Dog>::Categories::Wuff, [](auto& d){return d.makeSound()=="Wuff";} );
    dogs.addCategory( CategoryContainer<Dog>::Categories::WauWau, []()(auto& d){return d.makeSound()=="WauWau";} );
}
#包括
#包括
#包括
#包括
#包括
班犬
{
公众:
std::string makeSound(){return\u sound;}
void setSound(std::string sound){u sound=sound;}
私人:
std::string_sound=“Wuff”;
};
模板
类类别容器
{
公众:
使用objectContainer=std::vector;
使用pointerContainer=std::vector;
枚举类类别{Wuff,WauWau};//例如,狗因其发出的声音而不发音。
结构类别{
std::函数func;
指针容器指针;
类别(标准::函数f、对象容器和数据):func(f){
用于(自动和输入:数据)
if(func(i))
指针。向后放置(&i);
}
};
类别容器(尺寸){
data.resize(n);//构造这么多狗。
}
void addCategory(类别类别,标准::函数f){
索引[cat]=类别(f,数据);
}
私人:
对象容器数据;
std::无序映射索引;
};
int main()
{
类别包容犬(10只);
addCategory(CategoryContainer::Categories::Wuff,[](auto&d){return d.makeSound()==“Wuff”;});
dogs.addCategory(CategoryContainer::Categories::WauWau,[]()(auto&d){return d.makeSound()=“WauWau”;});
}
您将
[](auto&d){return d.makeSound()=“Wuff”}
作为一个函子传递,但
addCategory
声明为

void addCategory(Categories cat, std::function<bool()> f) {
void addCategory(类别类别、标准::函数f){

因此,函子应该接受零个参数,但实际上是接受而不是一个。std::function
您应该使用
std::function

,正如Alexey Guseynov(+1)所指出的,您的
func()
Category
中接收一个
T
对象

因此,正如建议的那样,应该是
std::function

你必须在三点上纠正这一点:

1)
std::function func;
变成
std::function func;

2)
Category(std::function f,objectContainer和data):func(f)
变成
Category(std::function f,objectContainer和data):func(f)

3)
void addCategory(Categories cat,std::function f)
变为
void addCategory(Categories cat,std::function f)

但这还不够

现在
Dog
makeSound()
方法与lambda函数中的const
Dog
实例化一起使用。因此
makeSound()
(不修改对象)应该在
const
方法中修改

std::string makeSound() const { return _sound; }
在这一点上,我有一些错误,因为
Dogs
std::unordered\u map
不兼容,因为(如果我理解正确的话)没有专门化
std::hash

但是,为了避免这个问题,如果你能改变

std::unordered_map<Categories, Category> indexed;
如果更改,则在
addCategory()
中,行

indexed[cat] = Category(f, data);
它给出了错误的原因(涉及构造函数),我不想进一步调查,但是

indexed.emplace(std::piecewise_construct,
                std::forward_as_tuple(cat),
                std::forward_as_tuple(f, data));

您应该能够编译您的示例。

重要的一点,也是尚未回答的一部分是,编译器如何处理这种情况。非常欢迎添加这一点。
indexed.emplace(std::piecewise_construct,
                std::forward_as_tuple(cat),
                std::forward_as_tuple(f, data));