I have my class for example TEST
in TEST.h I have
friend ostream& operator<< (ostream& out, const test& outstr);
in TEST.cc
ostream& operator <<(ostream& out, test& strout) {
out<< "TEST";
return out;
}
in main
test x;
cout<< x;
I recieve error message:
error: undefined reference to `operator<<(std::basic_ostream >&, test const&)
whats the problem?
You have const in the declaration:
friend ostream& operator<< (ostream& out, const test& outstr);
and no const in the implementation:
ostream& operator <<(ostream& out, MISSING CONST test& strout)
Adding const to the implementation should solve your issue.
Related
I want to wrap the following C++ code into python using pybind
class Galaxy {
public:
double x[3];
double v[3];
};
class GalaxyCatalogue {
public:
long n_tracers;
Galaxy *object;
GalaxyCatalogue(long n_tracers);
~GalaxyCatalogue();
};
GalaxyCatalogue::GalaxyCatalogue(long n_tracers) : n_tracers(n_tracers) {
std::cout << "from galaxies " << n_tracers << std::endl;
object = new Galaxy[n_tracers];
std::cout << "has been allocated " << std::endl;
}
GalaxyCatalogue::~GalaxyCatalogue() {
delete[] object;
}
The first problem I have is that Galaxy doesn't have a constructor, so I'm not sure what to do with that. Even if I declare an empty constructor I don't know how to treat the array in a way that I don't get an error when compiling. This is what I've tried:
#include <pybind11/pybind11.h>
#include <iostream>
namespace py = pybind11;
class Galaxy {
public:
Galaxy();
double x[3];
};
PYBIND11_MODULE(example, m){
py::class_<Galaxy>(m, "Galaxy")
.def(py::init<>())
.def_readwrite("x", &Galaxy::x);
}
This is how I compile it:
c++ -O3 -Wall -shared -std=c++11 -fPIC `python3 -m pybind11 --includes` gal.cpp -o example`python3-config --extension-suffix`
and this is the error I get:
In file included from gal.cpp:1:
/home/florpi/.conda/envs/virtualito/include/python3.5m/pybind11/pybind11.h: In instantiation of ‘pybind11::class_<type_, options>& pybind11::class_<type_, options>::def_readwrite(const char*, D C::*, const Extra& ...) [with C = Galaxy; D = double [3]; Extra = {}; type_ = Galaxy; options = {}]’:
gal.cpp:19:33: required from here
/home/florpi/.conda/envs/virtualito/include/python3.5m/pybind11/pybind11.h:1163:65: error: invalid array assignment
fset([pm](type &c, const D &value) { c.*pm = value; }, is_method(*this));
~~~~~~^~~~~~~
In file included from gal.cpp:1:
/home/florpi/.conda/envs/virtualito/include/python3.5m/pybind11/pybind11.h:64:5: error: ‘pybind11::cpp_function::cpp_function(Func&&, const Extra& ...) [with Func = pybind11::class_<type_, options>::def_readwrite(const char*, D C::*, const Extra& ...) [with C = Galaxy; D = double [3]; Extra = {}; type_ = Galaxy; options = {}]::<lambda(pybind11::class_<Galaxy>::type&, const double (&)[3])>; Extra = {pybind11::is_method}; <template-parameter-1-3> = void]’, declared using local type ‘pybind11::class_<type_, options>::def_readwrite(const char*, D C::*, const Extra& ...) [with C = Galaxy; D = double [3]; Extra = {}; type_ = Galaxy; options = {}]::<lambda(pybind11::class_<Galaxy>::type&, const double (&)[3])>’, is used but never defined [-fpermissive]
cpp_function(Func &&f, const Extra&... extra) {
^~~~~~~~~~~~
Thank you in advance.
In C++, you can't assign directly to an array, which is what pybind11 is trying to do inside its wrapping magic. In general, C++ arrays are not great abstractions for numerical arrays. As you've noticed, you can't even say galaxy.x = other_galaxy.x.
Your best bet is to use a higher-level library for matrices and vectors, which will
a) give you a much better experience writing your C++
b) perform better
c) map more cleanly to Python
Eigen is a good choice. pybind11 automatically knows how to map Eigen matrices and vectors to numpy arrays. Your Galaxy would become:
class Galaxy {
public:
Eigen::Vector3d x;
Eigen::Vector3d v;
};
If you absolutely can't do this, you'll have to supply manual getter/setter functions to the property, where you do your own conversion to and from python types:
https://pybind11.readthedocs.io/en/master/classes.html?highlight=def_property#instance-and-static-fields
I get the following error
In function w_Endline:
/home/prog2/in_out.c:113:19: error: assignment of read-only l ocation ‘*(sent + (sizetype)(endlen * 1ul))’
sent[endlen]='\0';
/home/prog2/in_out.c: In function ‘w_White’:
/home/prog2/in_out.c:119:19: warning: initialization discards ‘const’ qualifier from pointer target type
char* endlen=sent+whitelen;
/home/prog2/in_out.c:120:6: warning: implicit declaration of function ‘isspace’ [-Wimplicit-function-declaration]
while(endlen>sent &&isspace(*endlen))
FILES
1.in_out.c http://ideone.com/nI15F4
void w_Endline(const char* sent)
{
size_t endlen=strlen(sent)-1;
if(sent[endlen]=='\n')
sent[endlen]='\0';
}
void w_White(const char* sent)
{
size_t whitelen=strlen(sent);
char* endlen=sent+whitelen;
while(endlen>sent &&isspace(*endlen))
{
endlen='\0';
--endlen;
}
}
2.in_out.h http://ideone.com/lDxxhY
Dont use const in w_Endline if you are modifying the pointer also you need ctype.h header for isspace() function. Also in w_White function if you are assigning a const pointer the pointer also needs to be const.
char* endlen=sent+whitelen;
should be
const char* endlen=sent+whitelen;// because sent is const
Actually const qualifier means read-only
I'm trying to use the standard format for non-member function overloading for the ostream operator, but it will not work with a const second argument when I have an internal assignment to a vector iterator. The compiler gives the following error when a const argument is used: error: no match for 'operator=' in j = bus.owAPI::owBus::owCompList.std::vector...
Relevant parts of my Class are as follows:
class owBus{
public:
std::vector<owComponent> owCompList; //unsorted complete list
friend std::ostream&
operator<<(std::ostream& os, const owBus& bus );
};
with the non-member function:
std::ostream& operator<<(std::ostream& os, const owBus& bus ) {
//iterate through component vector
std::vector<owComponent>::iterator j;
for(j=bus.owCompList.begin(); j!=bus.owCompList.end(); j++) {
/*
os << (*j).getComponentID() << ": ";
os << (*j).getComponentType() << std::endl;
*/
}
return os;
}
This works fine if the const is removed from the friend declaration and the second argument in the function description, otherwise it give the error described above. I don't have an assignment operator defined for the class, but it's not clear to me why that should make a difference.
That's because you're trying to use a non-const iterator to iterate through a const object. Change the declaration of j to:
std::vector<owComponent>::const_iterator j;
or just use the C++11 style:
for (auto j : bus.owCompList) {
I made "T operator[](int i) const" and "T& operator[](int i)" for class A.
(and I also tried it for "const T& operator[](int i) const" and "T& operator[](int i)")
The operator print a value to distinguish which operator is called.
A a;
int k = a[0];
k = a[0];
const int l = a[0];
result : three calls of non-const version.
How can I call const version?
Should I use const class?
There is no chance to call a function that is const version without using const class?
You can use a const reference:
const A& b=a;
k=b[0];
Or a const cast:
k=const_cast<const A&>(a)[0];
I first store the 3 value into a pair of map like this:
void AddMenuAtlasTexture( int tag, const char* filename, const char* textureName )
{
map<const char*, const char*> _item;
_item.insert(pair<const char*, const char*>(filename, textureName));
m_texturesToLoad.insert(pair<int, map<const char*, const char*> >(tag, _item));
};
then I pass the value to another function like this:
map<const char*, const char*>::iterator _content;
int _tag = (*m_texturesToLoadIterator).first;
_content = (*m_texturesToLoadIterator).second.begin();
AtlasManagerSingleton->AddAtlas((*_content).first, (*_content).second, _tag);
the "textureName" is an absolute path like this kind: "/Users/eddy/Library/Application Support/iPhone Simulator/User/Applications/5FDE0091-2E93-42FE-BB62-05A16429551D/Ranch.app/../Documents/shop_tex.png"
my problem is the first function can get the "textureName" right, but the second function "AddAtlas" can not get the path, the "(*_content).second" is NULL.
and the "AddAtlas" prototype is:
void AtlasManager :: AddAtlas( const char *a_configFile, const char *a_spriteName, int a_nKey )
I develop this in iPhone dev using XCode.
use make_pair instead of pair<int, map<const char*, const char*> >.
use -> instead of *.
the texture loader is a map int -> const char* -> const char*. I don't see where you used the second index.
Probably this:
AtlasManagerSingleton->AddAtlas((*_content).first, (*_content).second, _tag)
Should be:
AtlasManagerSingleton->AddAtlas(_content->first, _content->second.begin()->second, _tag)