C++11 将可调用对象传递给构建某种多索引容器的对象
我正在尝试编写一个容器,它能够对对象进行分类,并存储分类函数为true的指针 我的问题是,它没有编译,而且由于我对诸如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。有没有一种方法可以
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函数中的constDog
实例化一起使用。因此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));