template function within non template class does not link - c++

I can not link template functions within non template class
I have:
class base {};
class mgr : base
{
template function a;
........
non template functions
};
template a access variables of class m
for example
static m<T>* ptr;
ptr = reinterpret_cast<m<T>*>( std::get<0>(d) );
ptr->m<T>::clear();
(m private section is friend of mgr)
in class g I want to use function a
static mgr mg;
mgr *p = &mg;
m<T> v = *( reinterpret_cast<T*>( p->a(p1,p2) );
note that func. a() return pointer to base (similar idea to void*) regardless of <T>
at the end of m.cpp I have (per specialization)
example:
template class m<string>;
at the end of mgr.cpp I have (per specialization)
example:
template pbase mgr::a<string>( ... );
hpp files used for declarations,
cpp files for definition (implementation)
watching the link map I can see that mgr linked template specialized
function a
however it failed to link it in g
any help would be appreciated
here is more code
mgr.hpp
#ifndef __mgr__mgr___
#define __mgr__mgr___
#include <iostream> // cout
#include <ostream> // cout
#include <string>
#include <vector>
#include <map>
#include <tuple>
#include <type_traits>
#include <limits>
#include <climits>
#include <exception>
using namespace std;
typedef string tInstName;
enum tInstType { Typ1 , Typ2 , Typ3 };
class mgr
{
public:
class MIObase {};
map<string,tuple<MIObase*,string,tInstType>> Imap;
template <class T> MIObase* getInstance ( const string& name , const iName& instname );
};
#endif
mgr.cpp
#include <ostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <utility>
#include <tuple>
#include <type_traits>
#include <typeinfo>
#include <limits>
#include <climits>
#include <exception>
#include "mgr.hpp"
#include "mfunc.hpp"
using namespace std;
template<>
pMIObase mgr::getInstance<string> ( const string& filename , const string& name )
{
tuple<pMIObase,string,tInstType> d;
static mfunc<string>* ptr;
static pMIObase ptr_;
auto it = Imap.find ( instname );
if ( it != Imap.end() )
{
d=Imap[instname];
ptr = reinterpret_cast<mfunc<string>*>( std::get<0>(d) );
ptr->mfunc<string>::clear();
ptr_ = std::get<0>(d);
cout<<instname <<" already exists .......\n";
return ptr_;
}
else
{
//mfunc<string> I;
ptr = new mfunc<string>;
d = make_tuple (reinterpret_cast<pMIObase>(ptr),name,Tstr);
Imap[instname] = d;
ptr->clear();
ptr_ = reinterpret_cast<pMIObase>(ptr);
return ptr_;
}
}
template pMIObase mgr::getInstance<string>(const string& filename , const tInstName& instname);
g.cpp
#include "mgr.hpp"
using namespace std;
void g()
{
static mgr mb;
mgr *pMIO=&mb;
// this one dose not link
static mfunc<string> &v = *( reinterpret_cast<mfunc<string>*>( pMIO->mgr::getInstance<string> ( ) ));
}

Related

pybind11 - Return a shared_ptr of std::vector

I have a member variable that stores a std::shared_ptr of std::vector<uint32_t>. I want to create a Python binding for test_func2() so that I can access that vector without any additional copy. Here is a skeleton code.
#include <vector>
#include <memory>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/numpy.h>
namespace py = pybind11;
class TestLoader
{
private:
std::shared_ptr<std::vector<uint32_t>> tileData;
public:
TestLoader();
~TestLoader();
void test_func1();
std::shared_ptr<std::vector<uint32_t>> test_func2() const;
};
void TestLoader::test_func1() {
tileData = std::make_shared<std::vector<uint32_t>>(100000000);
for(auto &x: *tileData){ x = 1;}
}
std::shared_ptr<std::vector<uint32_t>> TestLoader::test_func2() const{
return tileData;
}
The interface code is like the following:
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
namespace py = pybind11;
PYBIND11_MODULE(fltest_lib, m) {
py::class_<TestLoader, std::shared_ptr<TestLoader>>(m, "TestLoader")
.def(py::init<const std::string &>())
.def("test_func1", &TestLoader::test_func1)
.def("test_func2", &TestLoader::test_func2, py::return_value_policy::reference_internal);
}
However, this does not compile and I get a long error message. One particular line is the following:
/home/samee/fl_test/lib/pybind11/include/pybind11/cast.h:653:61: error: static assertion failed: Holder classes are only supported for custom types
653 | static_assert(std::is_base_of<base, type_caster<type>>::value,
| ^~~~~
Any help to circumvent this will be really helpful.
According to this issue, it doesn't work because std::vector<uint32_t> is not converted to a python type. So, you will have to return the dereferenced vector. To avoid copies, you can use PYBIND11_MAKE_OPAQUE
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/stl_bind.h>
#include "test_loader.h"
namespace py = pybind11;
PYBIND11_MAKE_OPAQUE(std::vector<uint32_t>);
PYBIND11_MODULE(fltest_lib, m) {
py::bind_vector<std::vector<uint32_t>>(m, "VectorUInt32");
py::class_<TestLoader, std::shared_ptr<TestLoader>>(m, "TestLoader")
.def(py::init())
.def("test_func1", &TestLoader::test_func1)
.def("test_func2",
[](const TestLoader& tl) -> const std::vector<uint32_t>& {
return *tl.test_func2();
}, py::return_value_policy::reference_internal);
}

c++ overloaded member function not found in 'ShaderProgram

What's wrong I'm doing? Strange, because signature of constructor is the same. The compiler says:
'ShaderProgram::ShaderProgram(std::vector< int*, std::allocator< _Ty >>)': overloaded member function not found in 'ShaderProgram'.
This error occures, when I use 3 files with code(below), but when I put this code in 1 file(main cpp) - it works
//main.cpp
#include <stdlib.h>
#include <stdio.h>
#include <vector>
#include "ShaderHelpers.h"
int main(int argc, const char* argv[]) {
int* a = new int(5);
int* b = new int(7);
ShaderProgram *sp = new ShaderProgram(std::vector<int*>{ a, b});
return 0;
}
================================================================
//shader.cpp
#include "ShaderHelpers.h"
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <vector>
#include <string>
ShaderProgram::ShaderProgram() { }
ShaderProgram::ShaderProgram(std::vector<int*> shaders)
{
Shaders = shaders;
for each (int* i in shaders)
{
std::cout << i;
}
}
ShaderProgram::~ShaderProgram()
{
std::cout << "delete";
}
===============================================================
//ShaderHelper.h
#pragma once
#include <string>
class ShaderProgram
{
public:
std::vector<int*> Shaders;
ShaderProgram(std::vector<int*> shaders);
~ShaderProgram();
private:
ShaderProgram();
};
I just needed to add
# include <vector>
into the ShaderHelper.h

Undefined reference when using template [duplicate]

This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 7 years ago.
I have a templated class named DataHandler
#ifndef DATAHANDLER_H
#define DATAHANDLER_H
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <set>
#include "constants.h"
template <typename T>
using Car = std::pair< T, T>;
template <typename T>
using SparseMatrix = std::vector< Car<T> >;
template <class T>
class DataHandler
{
public:
// initializes a new DataHandler only if none has been created,
// otherwise return the living instance
static DataHandler<T>* getInstance()
{
if(!dataHandler)
dataHandler = new DataHandler();
return dataHandler;
}
void readFile();
SparseMatrix<T>* getSparseBlue(){ return &sparseBlue; }
SparseMatrix<T>* getSparseRed(){ return &sparseRed; }
virtual ~DataHandler();
private:
// static DataHandler to ensure only one instance can be created
static DataHandler<T> *dataHandler;
// private constructor to use DataHandler as a Singleton
DataHandler();
int numElem = 0;
int m_rows, m_cols = -1;
#endif // DATAHANDLER_H
The source file is:
#include "data_handler.h"
#include <fstream>
#include <algorithm>
#include <omp.h>
#include <chrono>
using namespace std;
using namespace constants;
// Global static pointer used to ensure a single instance of the class.
template<typename T>
DataHandler<T>* DataHandler<T>::dataHandler = NULL;
template<typename T>
DataHandler<T>::DataHandler()
{
//ctor
}
template<typename T>
DataHandler<T>::~DataHandler()
{
//dtor
}
template<typename T>
void DataHandler<T>::readFile()
{
// do some stuff
}
// Instantiation of relevant templates
template class DataHandler<unsigned char>;
template class DataHandler<unsigned short int>;
In the last two lines I instantiate the templates which I define in main.cpp:
#include <iostream>
#include <chrono>
#include <fstream>
#include <algorithm>
#include "data_handler.h"
#include "dense_traffic_handler.h"
#include "sparse_traffic_handler.h"
#include "constants.h"
using namespace std;
// Check the number of rows/cols to choose between char or short int for the sparse case
bool matrixIsSmall()
{
return true;
}
void integerCase()
{
typedef unsigned char T;
DataHandler<T> *dh = DataHandler<T>::getInstance();
dh->readFile();
DenseTrafficHandler dth(dh); // ****** ERROR HERE *****
}
void charCase()
{
typedef unsigned char T;
DataHandler<T> *dh = DataHandler<T>::getInstance();
dh->readFile();
DenseTrafficHandler dth(dh); // ****** ERROR HERE *****
SparseTrafficHandler<T> sth;
set<unsigned short int> step = dh->getstep();
int currentStep = 0;
set<unsigned short int>::const_iterator stepToSave = step.begin();
}
int main(int argc, char *argv[])
{
if(matrixIsSmall())
charCase();
else
integerCase();
return 0;
}
Compiler gives me an error: undefined reference to DenseTrafficHandler::DenseTrafficHandler<unsigned short>(DataHandler<unsigned short>*)
DenseTrafficHandler header is like that:
#ifndef TRAFFICHANDLER_H
#define TRAFFICHANDLER_H
#include "constants.h"
#include "data_handler.h"
class DenseTrafficHandler
{
public:
template<typename T>
DenseTrafficHandler(DataHandler<T> *dh);
virtual ~DenseTrafficHandler();
private:
int m_cols, m_rows;
char* data;
char ** dense = NULL;
};
#endif // TRAFFICHANDLER_H
DenseTrafficHandler source is:
#include "dense_traffic_handler.h"
using namespace std;
using namespace constants;
template <typename T>
DenseTrafficHandler::DenseTrafficHandler(DataHandler<T> *datah)
{
DataHandler<T> *dh = datah;
dense = dh->getDense();
m_rows = dh->getm_rows();
m_cols = dh->getm_cols();
}
DenseTrafficHandler::~DenseTrafficHandler()
{
//dtor
}
So I have two questions:
Why do I receive this error and how can I manage it?
Is there a way in DataHandler source to not specify
template <typename T>
DataHandler<T>::functionName() for every function? (I mean something like using namespace Datahandler<T>)
You receive this error because compiler did not generate the code for this template type. One of solutions is to tell the compiler to do this explicitly by template instantiation:
add to your DenseTrafficHandler.cpp:
template class DenseTrafficHandler<unsigned short>;
Yes, just implement it in the header file. Reading more about it here.

Filter std::vector of std::string's

How can I produce an output vector which filters an input vector based on whether it starts with a certain sub-string or not. I'm using c++98 and boost.
This is as far as I got:
std::string stringToFilterBy("2");
std::vector<std::string> input = boost::assign::list_of("1")("2")("22")("33")("222");
std::vector<int> output;
boost::copy( input | boost::adaptors::filtered(boost::starts_with), std::back_inserter(output) );
You can use std::remove_copy_if instead:
#include <algorithm>
#include <iterator>
#include <vector>
struct filter : public std::unary_function<std::string, bool> {
filter(const std::string &by) : by_(by) {}
bool operator()(const std::string &s) const {
return s.find(by_) == 0;
}
std::string by_;
};
std::vector<std::string> in, out;
std::remove_copy_if(in.begin(), in.end(), std::back_inserter(out),
std::not1(filter("2")));
One way is:
#include <boost/algorithm/string/predicate.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/assign.hpp>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <string>
#include <iterator>
#include <vector>
int main() {
std::string stringToFilterBy("2");
std::vector<std::string> input =
boost::assign::list_of("1")("2")("22")("33")("222");
std::vector<int> output;
boost::copy(
input
| boost::adaptors::filtered(
boost::bind(
boost::starts_with<std::string,std::string>, _1, stringToFilterBy))
| boost::adaptors::transformed(boost::lexical_cast<int, std::string>),
std::back_inserter(output));
}
Or without boost::bind (this way avoids naming types and avoids the need for function pointers, but requires the addition of some single-use structs):
#include <boost/algorithm/string/predicate.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/assign.hpp>
#include <boost/lexical_cast.hpp>
#include <string>
#include <iterator>
#include <vector>
template<typename Range1T>
struct StartsWith_T {
StartsWith_T(Range1T const& test) : test(&test) {}
template<typename Range2T>
bool operator()(Range2T const& input) const {
return boost::starts_with(input, *test);
}
Range1T const* test;
};
template<typename Range1T>
StartsWith_T<Range1T> StartsWith(Range1T const& test) {
return StartsWith_T<Range1T>(test);
}
template<typename T>
struct LexicalCaster {
typedef T result_type;
template<typename Input>
T operator()(Input const& input) const {
return boost::lexical_cast<T>(input);
}
};
int main() {
std::string stringToFilterBy("2");
std::vector<std::string> input =
boost::assign::list_of("1")("2")("22")("33")("222");
std::vector<int> output;
using namespace boost::adaptors;
boost::copy(
input
| filtered(StartsWith(stringToFilterBy))
| transformed(LexicalCaster<int>()),
std::back_inserter(output));
}

error: request for member which is of non class type

I am using forward declaration and now I am getting an error referring to the class that uses the forward declaration...so fInstance forward declares fConfig and then the Helper class (a namespace - used for global access to functions) - getting t
fConfig.h
#ifndef FCONFIG_H
#define FCONFIG_H
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <fcntl.h>
#include "JWDSFork.h"
//#include "fInstance.h"
using namespace std;
class fConfig
{
private:
pid_t pid, w;
public:
pid_t cPid;
string name;
int group;
int instanceId;
int numInstance;
int tries;
bool reply;
bool debug;
bool service;
bool currentlyRunning;
time_t startTime;
time_t endTime;
string path;
fConfig();
virtual ~fConfig();
void start();
string intToString(int);
char* stringToChar(string);
};
#endif // FCONFIG_H
fInstance.h
#ifndef FINSTANCE_H
#define FINSTANCE_H
//#include "fConfig.h"
#include <vector>
#include <sys/types.h>
#include <string>
using namespace std;
class fConfig;
class fInstance
{
public:
fConfig* config;
pid_t pid;
vector<string> notes;
vector<time_t> times;
fInstance();
virtual ~fInstance();
};
#endif // FINSTANCE_H
Helper.h
#ifndef HELPER_H
#define HELPER_H
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <sstream>
#include <limits.h>
#include "fInstance.h"
using namespace std;
namespace Helper
{
extern string APPDIR;
bool errorCheck(int, char*);
string charToString(char*, int);
string longToString(unsigned long);
bool Contains(vector<fInstance>, fInstance);
string convertInt(int);
string convertDouble(double);
bool Read(int, char*, size_t);
bool Write(int, char*, size_t);
};
#endif // HELPER_H
Helper.cpp
//Helper.cpp - function that causes a problem
#include "Helper.h"
namespace Helper
{
bool Contains(vector<fInstance> a, fInstance b)
{
for(unsigned int i= 0; i < a.size(); i++ )
{
if(a[i].config.name == b.config.name)
{
return true;
}
}
return false;
}
}
I am getting these errors
error: request for member ‘name’ in ‘a.std::vector<_Tp, _Alloc>::operator[] [with _Tp = fInstance, _Alloc = std::allocator<fInstance>](((long unsigned int)i))->fInstance::config’, which is of non-class type ‘fConfig*’
That's a pretty unfriendly error message, but what it means is that the config member is a pointer, so you need to use the -> operator instead, ie.
if(a[i].config->name == b.config->name)
Assuming that you have an operator== overloaded for your type fInstance, you can write your function as (note also that you should pass your parameters a and b by reference-to-const)
#include<algorithm>
bool fInstance::operator==(const fInstance& other)
{
return config->name == other.config->name;
}
bool Contains(const vector<fInstance>& a, const fInstance& b)
{
return std::find_if(a.begin(), a.end(), b);
}
If you don't have an operator== in your fInstance class, you can use a C++11 lambda expression
bool Contains(const vector<fInstance>& a, const fInstance& b)
{
return std::find_if(a.begin(), a.end(),
[](const fInstance& i) { return i.config->name == b.config->name; });
}
And even better yet, you should encapsulate the name member into a member function of fInstance:
std::string fInstance::name() { return config->name; };
bool Contains(const vector<fInstance>& a, const fInstance& b)
{
return std::find_if(a.begin(), a.end(),
[](const fInstance& i) { return i.name() == b.name(); });
}
This increases encapsulation, decreases compilation times and makes the implementation of the fInstance class opaque to its clients. Your current implementation leaves the fConfig implementation transparant to clients. This decrease in encapsulation is called a violation of the Law of Demeter.