Help with a simple example
atom-moyer opened this issue · 2 comments
Hi all,
This is my first attempt at metaprogramming, so I am a total novice.
Right now, I am attempting to wrap a high performance hash table written in C++ and bind it to python/numpy. This requires that I create compiled version of all combinations of supported Key:Value pair types. A perfect place for metaprogramming I thought, compared to writing a python script that generates all of the typedef lines.
However I am having issues due to the lack of documentation or understanding I believe. Here is my current code which does not work because I am making hash tables of type: _Dict<brigand::type_<TYPE>, brigand::type_<TYPE>>
instead of _Dict<TYPE, TYPE>
. Therefore, I am getting errors like: error: no match for call to ‘(std::hash<brigand::type_<int> >)
.
Here is my current program:
(Note: I also have a class of _Dict<Key, Value>
implemented which I can compile with explicit types.)
#include <pybind11/pybind11.h>
namespace py = pybind11;
#include <brigand/brigand.hpp>
#include <brigand/sequences/list.hpp>
#include <brigand/algorithms/for_each.hpp>
using types = brigand::list<
float, int
>;
template<typename Key, typename Value>
void declare_Dict(const py::module& m) {
using Class = _Dict<Key, Value>;
std::string name = std::string("_Dict_") + typeid(Key).name() + std::string("_") + typeid(Value).name();
py::class_<Class>(m, name.c_str())
.def(py::init<>())
.def("__getitem__", &Class::__getitem__)
.def("__setitem__", &Class::__setitem__)
.def("__delitem__", &Class::__delitem__)
.def("__contains__", &Class::__contains__)
.def("__len__", &Class::__len__);
}
PYBIND11_MODULE(_sparsepy, m) {
m.doc() = "Fast and Memory Efficient Sparse Hash Tables for Python";
brigand::for_each<types>([&m](auto key) {
brigand::for_each<types>([&m, key](auto value) {
declare_Dict<key, value>(m);
});
});
}
Does anyone know how I can get the template type of Brigand::type_
? Am I doing something else wrong? Doing only one for loop at a time and "locking" one of types does not help with the errors, so the nested for_each
does not seem to be the issue.
Thanks!
Adam
Hi
the type_ is here so you can apply for_each
on any type, including void.
You can use the inside type by using ::type as shown here :
https://github.com/edouarda/brigand/blob/master/include/brigand/types/type.hpp
So you code should be :
brigand::for_each<types>([&m](auto key) {
brigand::for_each<types>([&m, key](auto value) {
using key_type = std::decay_t<decltype(key)>::type;
using value_type = std::decay_t<decltype(value)>::type;
declare_Dict<key_type, value_type>(m);
});
});
The decltype
retrieve the type of key and value. decay_t
ensures there is no const or & on the type before accessing the inner ::type. If you use C++20, using template lambda remove the need for this decay/decltype dance.
Tell us if it fixes your issue.
Thank you very much!
This works exactly as expected.