Linker generates undefined references derived templated class instance - code update with fix - class

I have the following abstract class -
#ifndef FOO_H
#define FOO_H
template <typename T>
class FOO{
public:
virtual void bar();
protected:
T foobar;
};
#endif
I then derive from this class -
#ifndef BAH_H
#define BAH_H
#include "foo.h"
template <typename T>
class BAH : public FOO<T>{
public:
BAH(){};
void bar(T const &);
};
#endif
////////////////////////////////////////////////
//Class Methods
////////////////////////////////////////////////
template<class T>
void BAH<T>::bar(T const &)
{
}
I then create main
#include "bah.h"
int main(int argc, char **argv)
{
FOO<int> *i_bah = new BAH<int>();
}
and on compilation % g++ main.cpp -I./
I now get -
/tmp/ccglncVU.o:(.rodata._ZTV3BAHIiE[vtable for BAH]+0x10): undefined reference to FOO<int>::bar()'
/tmp/ccglncVU.o:(.rodata._ZTV3FOOIiE[vtable for FOO<int>]+0x10): undefined reference toFOO::bar()'
collect2: ld returned 1 exit status

Related

I am not able to access private variables of class, I have used friend class

#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Movie
{
private:
std::string name{};
std::string rating{};
int watched{};
friend class movies;
public:
Movie(std::string name_val, std::string rating_val, int watched_val = 0);
// copy constructor
Movie(const Movie &source); //// this constructor
};
Movie::Movie(std::string name_val, std::string rating_val, int watched_val)
:name{name_val}, rating{rating_val}, watched{watched_val}{}
Movie::Movie(const Movie &source){
name = source.name;
rating = source.rating;
watched = source.watched;
}
class Movies
{
private:
std::vector<Movie> movie_obj;
public:
void get_movie_byname(Movie &abc) { std::cout << abc.name; }; // here is error abc.name
};
here is the error message
main.cpp:53:53: error: 'std::string Movie::name' is private within this context
53 | void get_movie_byname(Movie &abc) { std::cout << abc.name; };
| ^~~~
main.cpp:11:21: note: declared private here
11 | std::string name {};
| ^~~~
cant understand whats wrong...
i think friend of a class is friend of for given obj ( this--> ), and not for all obj,
if i removed copy constructor of Movie, error resolved!
cant understand relation between copy constructor and friend.
// issue solved turns out its just typo in Movies, declaration in friend declaration.

template of variadic template: parameter pack expects a type template

template <typename T, template <typename T, typename... Targs> class C>
void print_(const C<T,Targs>& arg, std::stringstream& ss)
{
std::for_each(arg.begin(), arg.end(), [&ss](const T& var) { ss << var; });
}
int main()
{
vector<int> vec{1,2,3};
std::stringstream ss;
print_(vec,ss);
}
main.cpp(8): error C2065: 'Targs': undeclared identifier
main.cpp(8): error C3544: 'Targs': parameter pack expects a type template
Names that are part of a template parameters list introduced by a template template parameter are valid only within that list.
In other terms, something like this is legal:
template<template<typename T, T> class U>
struct S {};
And you can use it as it follows:
template<typename T, T>
struct A {};
template<template<typename T, T> class U>
struct B {};
int main() {
B<A> b;
}
This isn't valid code instead:
template <typename T, template <typename T, typename... Targs> class C>
void print_(const C<T,Targs> &, std::stringstream &);
Targs is no longer a valid name after the first > symbol (the one that follows immediately Targs itself).
The compiler keeps saying it to you quite clearly: undeclared identifier.
That being said, in your question there isn't an actual question, so I don't know what you expect from an answer but to tell you why that's an error.
this worked!
#include <iostream>
#include <sstream>
#include <vector>
#include <algorithm>
using namespace std;
template <typename T, template <typename T, typename... > class C, class... Args>
void print_(std::stringstream& ss, const C<T,Args...>& arg)
{
std::for_each(arg.begin(), arg.end(), [&ss](const T& var) { ss << var << ":"; });
}
int main()
{
vector<int> vec{1,2,3};
std::stringstream ss;
print_(ss, vec);
cout << ss.str();
}

boost.python MSVC12 linker errors when exposing classes with docstring_options

I regularly expose c++ classes to python using boost.python & MSVC 12 (dynamic linking). Recently I have been trying to include documentation using the "docstring_options" class. The documentation examples work fine:
http://www.boost.org/doc/libs/1_54_0/libs/python/doc/v2/docstring_options.html
However, when I include a class and expose it I get linker errors:
error LNK2019: unresolved external symbol "void __cdecl boost::throw_exception(class std::exception const &)" (?throw_exception#boost##YAXABVexception#std###Z) referenced in function "public: __thiscall boost::detail::shared_count::shared_count(void *,struct boost::python::converter::shared_ptr_deleter)"
I'm sure there is probably something simple I'm missing but I can't figure it out.
Many thanks in advance!
sample code spliced from the boost examples that gives this error for me.
#include <string>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/args.hpp>
#include <boost/python/docstring_options.hpp>
#include <boost/python.hpp>
struct World
{
void set(std::string msg) { this->msg = msg; }
std::string greet() { return msg; }
std::string msg;
};
int foo1(int i) { return i; }
int foo2(long l) { return static_cast<int>(l); }
int bar1(int i) { return i; }
int bar2(long l) { return static_cast<int>(l); }
namespace {
void wrap_foos()
{
using namespace boost::python;
def("foo1", foo1, arg("i"), "foo1 doc");
def("foo2", foo2, arg("l"), "foo2 doc");
}
void wrap_bars()
{
using namespace boost::python;
bool show_user_defined = true;
bool show_signatures = false;
docstring_options doc_options(show_user_defined, show_signatures);
def("bar1", bar1, arg("i"), "bar1 doc");
def("bar2", bar2, arg("l"), "bar2 doc");
class_<World>("World")
.def("greet", &World::greet)
.def("set", &World::set)
;
}
}
BOOST_PYTHON_MODULE(boost_py_doc_demo)
{
boost::python::docstring_options doc_options(false);
wrap_foos();
wrap_bars();
}
I compiled the latest version of boost (1.63) and now the problem has gone. I guess my old libraries were incomplete in some way.

Unmanaged method member being used as a delegate in managed class

I have a project where I am expanding existing native C++ compatible code functionality for a customer-facing library by integrating a driver from a managed DLL, which seems like the opposite direction for most marshaling questions. Since there can be multiple devices using this one driver, each device needs to be its own object, with its own callback methods. This integration will take the form of a native wrapper DLL that exposes the native class interface to the customer-facing library, which will pass an instance of a member method callback function pointer to the DLL. I need to pass a native method member instance (non-static) as a delegate to the managed wrapper class. The managed wrapper class uses GetDelegateForFunctionPointer, which works to marshal static native pointers to a delegate, but I can't find any information if it works with instances. GetDelegateForFunctionPointer also takes a System::IntPtr argument for the function pointer, but I'm also not sure if System::IntPtr works for instances, and when compiling in VC++2008 I'm being presented an error C3867 for attempting this.
Managed wrapper header:
//somemanagedclass.hpp
#pragma once
using namespace System;
using namespace ExternalManagedLibrary;
namespace SomeNameSpace
{
public ref class SomeManagedClass
{
public:
SomeManagedClass();
~SomeManagedClass();
delegate void CallbackHandler(const wchar_t*, int);
CallbackHandler^ CallbackEvent;
void RegisterCallback(IntPtr callbackEvent);
private:
ExternalManagedClass^ externalManagedClass;
void OnCallback(Object^ sender, ValueEventArgs<String^>^ e);
};
}
Managed wrapper source:
//somemanagedclass.cpp
#include "somemanagedclass.hpp"
#include <vcclr.h>
using namespace System;
using namespace Runtime::InteropServices;
namespace SomeNameSpace
{
SomeManagedClass::SomeManagedClass()
{
externalManagedClass = gcnew ExternalManagedClass();
externalManagedClass->CallbackEvent += gcnew EventHandler<ValueEventArgs<String^>^>(this, &SomeManagedClass::OnCallback);
}
SomeManagedClass::~SomeManagedClass()
{
externalManagedClass->CallbackEvent -= gcnew EventHandler<ValueEventArgs<String^>^>(this, &SomeManagedClass::OnCallback);
}
void SomeManagedClass::OnCallback(Object^ sender, ValueEventArgs<String^>^ e)
{
String^ some_string = String::Copy(e->Value);
cli::pin_ptr<const wchar_t> pinned_string = &PtrToStringChars(some_string)[0];
const wchar_t* p = pinned_string;
CallbackEvent(pinned_string, some_string->Length);
}
void SomeManagedClass::RegisterCallback(IntPtr callbackEvent)
{
CallbackEvent = (CallbackHandler^)(Marshal::GetDelegateForFunctionPointer(callbackEvent, CallbackHandler::typeid));
}
}
Native wrapper interface:
//somenativeinterface.hpp
#ifdef DLL_EXPORT
#define IMPORT_EXPORT __declspec(dllexport)
#else
#define IMPORT_EXPORT __declspec(dllimport)
#endif //DLL_EXPORT
typedef void (*NativeCallback)(const unsigned char*, unsigned long);
class IMPORT_EXPORT SomeNativeInterface
{
public:
//class factory
static SomeNativeInterface* Create(void);
static void Destroy(SomeNativeInterface* clInterface);
virtual void CallbackInit(NativeCallback fnNativeCallbackInit);
};
Native wrapper header:
//somenativeclass.hpp
#pragma once
#include "somenativeinterface.hpp"
#include "somemanagedclass.hpp"
#include <vcclr.h>
using namespace SomeNameSpace;
class IMPORT_EXPORT SomeNativeClass : public SomeNativeInterface
{
public:
SomeNativeClass();
~SomeNativeClass();
void CallbackInit(NativeCallback fnNativeCallbackInit); //can this take an instance?
private:
NativeCallback fnNativeCallback;
void OnNativeCallback(const wchar_t* cString, int iSize);
gcroot<SomeManagedClass^> wrapper; //warning C4251
};
Native wrapper source:
//somenativeclass.cpp
#include "somenativeclass.hpp"
#include <vcclr.h>
#include <string.h>
using namespace System;
using namespace Runtime::InteropServices;
SomeNativeInterface* SomeNativeInterface::Create()
{
return ((SomeNativeInterface*) new SomeNativeClass());
}
void SomeNativeInterface::Destroy(SomeNativeInterface* instance)
{
delete instance;
}
SomeNativeClass::SomeNativeClass()
{
wrapper = gcnew SomeManagedClass();
}
SomeNativeClass::OnNativeCallback(const wchar_t* cString, int iSize)
{
std::auto_ptr<char> pcConvertedString(new char[iSize+1]);
size_t iCharsConverted;
if (wcstombs_s(&iCharsConverted, (char*)*pcConvertedString, iSize+1, cString, iSize) == 0)
{
if (iCharsConverted > 0xFFFFFFFF)
iCharsConverted = 0xFFFFFFFF; //truncate
fnNativeCallback((const unsigned char*)*pcConvertedString, (unsigned long)(iCharsConverted));
}
}
SomeNativeClass::CallbackInit(NativeCallback fnNativeCallbackInit)
{
fnNativeCallback = fnNativeCallbackInit;
wrapper->RegisterCallback(System::IntPtr(this->OnNativeCallback)); //error C3867
}

Access to the same class instance from qml

I'm using Qt 5.1.0 and QtQuick 2.0.
I've just learned how to exchange data and method between qml and C++. In detail, I want to expose a (nested) structure, so I created classes which contains the required properties and methods.
It works, but I cannot share the very same instance between C++ and qml. Changing something from C++ side leads to no changes in qml side.
A short example:
main.cpp
#include <QtGui/QGuiApplication>
#include <QtQml>
#include "qtquick2applicationviewer.h"
#include "myclass.h"
int main(int argc, char *argv[]) {
QGuiApplication app(argc, argv);
qmlRegisterType<MyClass>("MyLibrary", 1, 0, "MyClass");
MyClass *myclass = new MyClass();
Category *cat = new Category();
cat->setName("foo");
myclass->append(cat);
qDebug() << myclass->categoriesCount(); // returns 1 OK!
QtQuick2ApplicationViewer viewer;
viewer.setMainQmlFile(QStringLiteral("qml/main.qml"));
viewer.show();
return app.exec();
}
myclass.h
#include <QObject>
class Category : public QObject {
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName)
public:
Category() {}
QString name() const { return m_name; }
void setName(QString name) { m_name = name; }
private:
QString m_name;
};
class MyClass : public QObject {
Q_OBJECT
Q_PROPERTY(QList<QObject*> categories READ categories NOTIFY categoriesChanged)
Q_PROPERTY(int categoriesCount READ categoriesCount)
public:
QList<QObject*> categories() const { return m_categories; }
void clear() { m_categories.clear(); }
void append(Category *category) { m_categories.append(category); }
int categoriesCount() const { return m_categories.count(); }
private:
QList<QObject*> m_categories;
signals:
void categoriesChanged();
};
main.qml
import QtQuick 2.0
import MyLibrary 1.0
Item {
id: root
width: 360
height: 360
Text {
id: foo
text: myclass.categoriesCount // writes 0 -> should be 1
}
MyClass {
id: myclass
}
}
I'm afraid the qml engine accesses to a different instance of the class myclass created in the main file.