I'm trying to write a container that is able to categories objects and store pointers for which a categorisation function is true.
My problem is, that it does not compile and since I'm inexperienced in regard to callables like std::function or lambdas, I'm not sure how to fix it.
I want such a container, since I've the need to get some "Categories" often - and this makes it easy to cache the results. Especially if, in this example, the Dogs change their sound, the Categories can simply be recreated (since the callable is still there).
What is more, I'm intersted in a solution that delivers good performance. As I read, std::functions are unlikely to be inlined. Is there a way to deliver inlined-performance?
The compiler says:
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";} );
And here is my code:
#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";} );
}
Aucun commentaire:
Enregistrer un commentaire