Reputation: 109
I am trying to initialize a map from strings to unique pointers from cppyy. I am able to make a vector of pointers without issue, but I get some complaints from cppyy when I make a map. Here are my classes:
import cppyy
import cppyy.gbl as Cpp
cppyy.cppdef(r"""\
#include <cmath>
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <memory>
class Zoo
{
// generic Zoo interface
public:
Zoo() = default;
virtual ~Zoo() = default;
virtual void printAnimals() = 0;
};
template<typename TAnimalType> class SpecificZoo:
public Zoo
{
public:
virtual std::vector<TAnimalType> getAnimals() = 0;
};
class Bird{
};
class Fish{
};
class Aquarium: public SpecificZoo<Fish>{
public:
void printAnimals() override {
std::cout << "fish";
}
std::vector<Fish> getAnimals() override {
return {};
}
};
class Aviary: public SpecificZoo<Bird>{
public:
void printAnimals() override {
std::cout << "Birds";
}
std::vector<Bird> getAnimals() override {
return {};
}
};
int main(){
std::vector<std::unique_ptr<Zoo>> zoos{};
auto aquarium = std::make_unique<Aquarium>();
zoos.push_back(std::move(aquarium));
auto aviary = std::make_unique<Aviary>();
zoos.push_back(std::move(aviary));
std::cout << zoos.size() << std::endl;
std::cout << "Done making zoo vector" << std::endl;
std::map<std::string, std::unique_ptr<Zoo>> zooMap{};
auto aquarium2 = std::make_unique<Aquarium>();
auto aviary2 = std::make_unique<Aviary>();
zooMap.emplace("aquarium", std::move(aquarium2));
zooMap.emplace("aviary", std::move(aviary2));
std::cout << zooMap.size() << std::endl;
std::cout << "Done making zoo map" << std::endl;
}
""")
To make a vector of pointers I can do:
zoos = Cpp.std.vector[Cpp.std.unique_ptr[Cpp.Zoo]]()
print("Created zoos")
aquarium = Cpp.Aquarium()
aviary = Cpp.Aviary()
zoos.push_back(Cpp.std.move(aquarium))
zoos.push_back(Cpp.std.move(aviary))
However, to make a map I have tried:
zooDict = Cpp.std.map[Cpp.std.string, Cpp.std.unique_ptr[Cpp.Zoo]]()
aquarium2 = Cpp.std.make_unique[Cpp.Aquarium]()
aviary2 = Cpp.std.make_unique[Cpp.Aviary]()
print(aquarium2)
zooDict.emplace('aquarium', Cpp.std.move(aquarium2))
zooDict.emplace('aviary', Cpp.std.move(aviary2))
print(f'Zoo dict created? {zooDict}')
for key, val in zooDict:
print(key, val)
which crashes with this error:
IncrementalExecutor::executeFunction: symbol '_ZN9__gnu_cxx13new_allocatorISt13_Rb_tree_nodeISt4pairIKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt10unique_ptrI3ZooSt14default_deleteISB_EEEEE9constructISF_JS8_8AquariumEEEvPT_DpOT0_' unresolved while linking symbol '__cf_15'!
You are probably missing the definition of void __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::unique_ptr<Zoo, std::default_delete<Zoo> > > > >::construct<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::unique_ptr<Zoo, std::default_delete<Zoo> > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, Aquarium>(std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::unique_ptr<Zoo, std::default_delete<Zoo> > >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, Aquarium&&)
Maybe you need to load the corresponding shared library?
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[5], line 6
3 aviary2 = Cpp.std.make_unique[Cpp.Aviary]()
5 print(aquarium2)
----> 6 zooDict.emplace('aquarium', Cpp.std.move(aquarium2))
7 zooDict.emplace('aviary', Cpp.std.move(aviary2))
9 print(f'Zoo dict created? {zooDict}')
ValueError: Template method resolution failed:
std::pair<std::_Rb_tree_iterator<std::pair<const std::string,std::unique_ptr<Zoo,std::default_delete<Zoo> > > >,bool> std::map<std::string,std::unique_ptr<Zoo,std::default_delete<Zoo> > >::emplace(std::string&& __args, Aquarium&& __args) =>
ValueError: nullptr result where temporary expected
I have also tried not creating unique_ptr
s:
zooDict = Cpp.std.map[Cpp.std.string, Cpp.std.unique_ptr[Cpp.Zoo]]()
aquarium2 = Cpp.Aquarium()
aviary2 = Cpp.Aviary()
zooDict.emplace('aquarium', Cpp.std.move(aquarium2))
zooDict.emplace('aviary', Cpp.std.move(aviary2))
print(f'Zoo dict created? {zooDict}')
for key, val in zooDict:
print(key, val)
which crashes with this error:
IncrementalExecutor::executeFunction: symbol '_ZN9__gnu_cxx13new_allocatorISt13_Rb_tree_nodeISt4pairIKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt10unique_ptrI3ZooSt14default_deleteISB_EEEEE9constructISF_JS8_8AquariumEEEvPT_DpOT0_' unresolved while linking symbol '__cf_12'!
You are probably missing the definition of void __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::unique_ptr<Zoo, std::default_delete<Zoo> > > > >::construct<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::unique_ptr<Zoo, std::default_delete<Zoo> > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, Aquarium>(std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::unique_ptr<Zoo, std::default_delete<Zoo> > >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, Aquarium&&)
Maybe you need to load the corresponding shared library?
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[5], line 5
2 aquarium2 = Cpp.Aquarium()
3 aviary2 = Cpp.Aviary()
----> 5 zooDict.emplace('aquarium', Cpp.std.move(aquarium2))
6 zooDict.emplace('aviary', Cpp.std.move(aviary2))
8 print(f'Zoo dict created? {zooDict}')
ValueError: Template method resolution failed:
std::pair<std::_Rb_tree_iterator<std::pair<const std::string,std::unique_ptr<Zoo,std::default_delete<Zoo> > > >,bool> std::map<std::string,std::unique_ptr<Zoo,std::default_delete<Zoo> > >::emplace(std::string&& __args, Aquarium&& __args) =>
ValueError: nullptr result where temporary expected
And finally I have tried not moving the objects and not making pointers, which doesn't crash, but it still creates a warning message
zooDict = Cpp.std.map[Cpp.std.string, Cpp.std.unique_ptr[Cpp.Zoo]]()
aquarium2 = Cpp.Aquarium()
aviary2 = Cpp.Aviary()
zooDict.emplace('aquarium', aquarium2)
zooDict.emplace('aviary', aviary2)
print(f'Zoo dict created? {zooDict}')
for key, val in zooDict:
print(key, val)
IncrementalExecutor::executeFunction: symbol '_ZN9__gnu_cxx13new_allocatorISt13_Rb_tree_nodeISt4pairIKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt10unique_ptrI3ZooSt14default_deleteISB_EEEEE9constructISF_JS8_R8AquariumEEEvPT_DpOT0_' unresolved while linking symbol '__cf_12'!
You are probably missing the definition of void __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::unique_ptr<Zoo, std::default_delete<Zoo> > > > >::construct<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::unique_ptr<Zoo, std::default_delete<Zoo> > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, Aquarium&>(std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::unique_ptr<Zoo, std::default_delete<Zoo> > >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, Aquarium&)
Maybe you need to load the corresponding shared library?
Is there something I should be doing to not get this error message? Am I creating this object correctly?
Edit to respond to @273k 's answer. Doing that almost works, I get a warning the first time the cell runs, but if I run it again the warning disappears. (python's string is automatically converted to Cpp.std.string but even when I do it explicitly the warning persists.)
zooDict = Cpp.std.map[Cpp.std.string, Cpp.std.unique_ptr[Cpp.Zoo]]()
aquarium2 = Cpp.Aquarium()
aviary2 = Cpp.Aviary()
zooDict.emplace(Cpp.std.make_pair[Cpp.std.string, Cpp.std.unique_ptr[Cpp.Zoo]]('aquarium', Cpp.std.move(aquarium2)))
zooDict.emplace(Cpp.std.make_pair[Cpp.std.string, Cpp.std.unique_ptr[Cpp.Zoo]]('aviary', Cpp.std.move(aviary2)))
print(f'Zoo dict created? {zooDict}')
for key, val in zooDict:
print(key, val)
val.printAnimals()
returns:
IncrementalExecutor::executeFunction: symbol '_ZN9__gnu_cxx13new_allocatorISt13_Rb_tree_nodeISt4pairIKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt10unique_ptrI3ZooSt14default_deleteISB_EEEEE9constructISF_JRS2_IS8_SE_EEEEvPT_DpOT0_' unresolved while linking symbol '__cf_13'!
You are probably missing the definition of void __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::unique_ptr<Zoo, std::default_delete<Zoo> > > > >::construct<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::unique_ptr<Zoo, std::default_delete<Zoo> > >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::unique_ptr<Zoo, std::default_delete<Zoo> > >&>(std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::unique_ptr<Zoo, std::default_delete<Zoo> > >*, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::unique_ptr<Zoo, std::default_delete<Zoo> > >&)
Maybe you need to load the corresponding shared library?
IncrementalExecutor::executeFunction: symbol '_ZN9__gnu_cxx13new_allocatorISt13_Rb_tree_nodeISt4pairIKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt10unique_ptrI3ZooSt14default_deleteISB_EEEEE9constructISF_JPS2_IS8_SE_EEEEvPT_DpOT0_' unresolved while linking symbol '__cf_14'!
You are probably missing the definition of void __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::unique_ptr<Zoo, std::default_delete<Zoo> > > > >::construct<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::unique_ptr<Zoo, std::default_delete<Zoo> > >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::unique_ptr<Zoo, std::default_delete<Zoo> > >*>(std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::unique_ptr<Zoo, std::default_delete<Zoo> > >*, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::unique_ptr<Zoo, std::default_delete<Zoo> > >*&&)
Maybe you need to load the corresponding shared library?
Zoo dict created? <cppyy.gbl.std.map<std::string,std::unique_ptr<Zoo,std::default_delete<Zoo> > > object at 0x55588a7f6fc0>
aquarium <cppyy.gbl.Zoo object at 0x55588a997be0 held by std::unique_ptr<Zoo,std::default_delete<Zoo> > at 0x55588b270bb0>
fish
aviary <cppyy.gbl.Zoo object at 0x55588a982cf0 held by std::unique_ptr<Zoo,std::default_delete<Zoo> > at 0x55588b364e00>
Birds
on the first try, but then running it again returns:
Zoo dict created? <cppyy.gbl.std.map<std::string,std::unique_ptr<Zoo,std::default_delete<Zoo> > > object at 0x55588a7f6fc0>
aquarium <cppyy.gbl.Zoo object at 0x55588a997be0 held by std::unique_ptr<Zoo,std::default_delete<Zoo> > at 0x55588b270bb0>
fish
aviary <cppyy.gbl.Zoo object at 0x55588a982cf0 held by std::unique_ptr<Zoo,std::default_delete<Zoo> > at 0x55588b364e00>
Birds
Upvotes: 0
Views: 148
Reputation: 38341
std::map::emplace(Args&&... args)
expects std::map::value_type
in args
, that type is std::pair<const std::string, std::unique_ptr<Zoo>>
.
zooDict.emplace('aquarium', Cpp.std.move(aquarium2))
should be smth like (I am not familiar with cppyy)
zooDict.emplace(Cpp.std.make_pair('aquarium', Cpp.std.move(aquarium2)))
and 'aquarium'
maybe needs to change to Cpp.std.string('aquarium')
Upvotes: 0