I want to search for a small image from a large one, my algorithm is:
search for the first line
if first line matches, then compare the rest
I want to use boost::algorithm::boyer_moore to do the line searching, it works fine with std::string:
#include <string>
using namespace std;
#include "boost/algorithm/searching/boyer_moore.hpp"
using namespace boost::algorithm;
int main() {
string s;
boyer_moore<string::iterator> bm(s.begin(), s.end()); // it compiles
}
the code compiles, but this one not:
#include "boost/mpl/vector.hpp"
using namespace boost;
#include "boost/gil/gil_all.hpp"
using namespace boost::gil;
#include "boost/algorithm/searching/boyer_moore.hpp"
using namespace boost::algorithm;
int main() {
typedef rgba8_image_t image_t;
typedef image_t::view_t view_t;
view_t vw;
boyer_moore<view_t::x_iterator> bm(vw.row_begin(0), vw.row_end(0)); // compile error
}
Both of them are iterators, what's wrong with the second one?
Thanks.
According to the docs the algorithm uses an auxiliary data structure called skip_table. By default (when the value_type of the iterator is not a char or unsigned char) this table uses a tr1::unordered_map, and this requires that gil::pixel be hash-able. So you have two options: you either change the default skip_table by specializing BM_traits for your iterator (this is sadly undocumented), or you make gil::pixel hash-able. For the latter you can create a std::size_t hash_value(pixel<ChannelValue,Layout> const& val) inside the namespace boost::gil. The following compiles with g++ 4.9.0 and Visual Studio 2013 (and does nothing):
#include <boost/functional/hash.hpp> //ADDED
#include <boost/mpl/vector.hpp>
#include <boost/gil/gil_all.hpp>
#include <boost/algorithm/searching/boyer_moore.hpp>
using namespace boost;
using namespace boost::gil;
using namespace boost::algorithm;
namespace boost {
namespace gil
{
template <typename ChannelValue, typename Layout>
std::size_t hash_value(pixel<ChannelValue, Layout> const& b)
{
std::size_t seed = 0;
for (int c = 0; c<num_channels<pixel<ChannelValue, Layout> >::value; ++c)
hash_combine(seed, b[c]);
return seed;
}
}
}
namespace std { //ADDED
template <typename ChannelValue, typename Layout>
struct hash<boost::gil::pixel<ChannelValue,Layout> > {
size_t operator ()(boost::gil::pixel<ChannelValue, Layout> const& value) const {
return hash_value(value);
}
};
}
int main() {
typedef rgba8_image_t image_t;
typedef image_t::view_t view_t;
view_t vw;
boyer_moore<view_t::x_iterator> bm(vw.row_begin(0), vw.row_end(0)); // compile error
}
Related
Consider the following code -
#include <variant>
#include <string>
int p(std::variant<bool, std::string> v) {
return v.index();
}
int main() {
return p("ad");
}
instead of choosing std::string, p will be instantiated with variant containing bool (I want std::string), well this can be fixed using explicitly specifying std::string but that is too much work 😊, I tried providing different overloads but it doesn't seem to work.
This has been fixed in C++20. See P0608 for a discussion of this exact case.
You can use the string literal suffix s to create an std::string object directly
return p("ad"s);
If the suffix isn't available then you need to add using namespace std::literals, using namespace std::string_literals or using namespace std::literals::string_literals
That said, I've tried your code on Wandbox and p("ad") returns 1 for me
Such code:
#include <variant>
#include <string>
int p(std::variant<bool, std::string> v) {
return v.index();
}
template<size_t N>
int p(const char (&s)[N]) {
return p(std::string(s));
}
int main() {
return p("ad");
}
returns 1.
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.
I have this class (hashMap.h):
#pragma once
#include <iostream>
#include <vector>
#include <string>
#include "functions.h"
using std::cout;
using std::vector;
using std::endl;
using std::string;
class hashMap
{
public:
explicit hashMap(int hashEntrySize = 101) : hashVector(nextPrime(2 * hashEntrySize)), currentSize{ 0 }
{}
bool containsKey(const string & searchKey);
bool containsVector(const vector<string> searchVector);
void insert(const string & keyTarget, const vector<string> & insertVector);
void insertAfterReHash(const string & keyTarget, const vector<string> & insertVector);
int getCurrentSize() const;
void assignKey(string & newKey);
private:
enum EntryType { ACTIVE, EMPTY, DELETED };
struct hashEntry
{
vector<string> vectorValue;
EntryType status;
int keyID;
string key;
hashEntry(EntryType s = EMPTY)
:status(s), keyID{ -1 } {}
};
size_t hashFunction(const string & key);
bool isActive(int currentPos) const;
int findPos(const string & keyTarget);
void reHash();
vector<hashEntry> hashVector;
int currentSize;
};
And a function header file (functions.h):
#pragma once
#include <iostream>>
#include <vector>
#include <string>
#include <fstream>
using std::string;
using std::cout;
using std::vector;
using std::endl;
using std::cin;
using std::ifstream;
using std::getline;
hashMap computeAdjacentWords(const vector<string> & words) //error at this line
{
hashMap hm(500);
//do stuff with object
return hm;
}
And the main file:
#include <iostream>>
#include <vector>
#include <string>
#include <fstream>
#include "hashMap.h"
using std::string;
using std::cout;
using std::vector;
using std::endl;
using std::cin;
using std::ifstream;
using std::getline;
int main()
{
vector<string> words;
string line;
ifstream dictionaryFile;
dictionaryFile.open("largedictionary.txt");
words = readinWords(dictionaryFile);
dictionaryFile.close();
hashMap hm = computeAdjacentWords(words);
return 0;
}
I created the hashMap class and I want to be able to return a hashMap object, but this is giving me an error of "Error C4430 missing type specifier - int assumed." What am I doing wrong?
I put the code in files and nicely asked the compiler to do its job. This is the first warning from the list:
$ cc main.cpp -c
In file included from main.cpp:5:
In file included from ./hashMap.h:6:
./functions.h:16:1: error: unknown type name 'hashMap'
hashMap computeAdjacentWords(const vector<string> & words) //error at this line
^
The compiler doesn't know what hashMap is. When it reaches the line with the error, the hashMap symbol was not yet declared or defined.
You shouldn't define functions in header files.
Rename functions.h to functions.cpp, add #include "functions.h" at the end of the list of includes.
Create a new file functions.h that contains only the declarations of the functions (the function header) and the types they use:
#ifndef __FUNCTIONS_H__
#define __FUNCTIONS_H__
#pragma once
//#include <iostream>
#include <vector>
#include <string>
//#include <fstream>
#include "hashMap.h"
using std::string;
using std::vector;
// Do you really need all these types here?
using std::cout;
using std::endl;
using std::cin;
using std::ifstream;
using std::getline;
hashMap computeAdjacentWords(const vector<string> & words);
#endif // __FUNCTIONS_H__
You are including functions.h from hashmap.h BEFORE the hashMap class is defined. As such, when the compiler reads functions.h, the hashMap class is not defined.
For some reason, I need to have a map from arbitrary huge number to double and I tried to implement it with c++98 (and I have to) and Xcode but it doesn't work:
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <set>
#include "gurobi_c++.h"
#include <sstream>
#include "boost/tuple/tuple.hpp"
#include "boost/tuple/tuple_comparison.hpp"
#include "boost/tuple/tuple_io.hpp"
#include <cmath>
#include <gmp.h>
using namespace std;
using namespace ::boost::tuples;
using namespace ::boost;
int main()
{
map<mpz_t, double>J;
mpz_t a,b,c,n;
string tempstring;
int xrange=5,yrange=5,component=5;
mpz_set_str(n,"11", 10);
J[n]=-1;
return 0;
}
The error shown is: Array initializer must be an initializer list. Could someone help me with it? Thank you:)
Here's the detail error page:
I don't know the details of mpz_t. However, it appears to be an array.
You can get around the problem by defining a class to be used as the key in your map.
I am able to create an executable using the following code with g++ 4.8.2.
#include <map>
using namespace std;
typedef int (mpz_t)[2];
struct MyKey
{
// Add a proper implementation of a constructor
// with mpz_t.
MyKey(mpz_t in) {}
// Add a proper implementation of copy constructor.
MyKey(MyKey const& copy) {}
// Add a proper implementation of assignment operator.
MyKey& operator=(MyKey const& rhs)
{
return *this;
}
bool operator<(MyKey const& rhs) const
{
// Add a proper implementation.
return false;
}
mpz_t n;
};
int main()
{
map<MyKey, double> J;
mpz_t n;
J[n] = 1.0;
return 0;
}
I'm using boost 1.52 and Visual Studio 2010.
I'm wondering why I can't enforce on the elements returned by boost::adaptors::indirected.
This sample code shows what I'm trying to achieve:
#include <vector>
#include <string>
#include <boost/range/adaptor/indirected.hpp>
#include <boost/foreach.hpp>
int main() {
using std::vector;
using std::string;
typedef vector<string*> type;
type range;
range.push_back(new string("42"));
type const& const_range = range;
// This is ok to compile
BOOST_FOREACH(string const& foo, const_range | boost::adaptors::indirected) {
//...
}
// I don't want this to compile
BOOST_FOREACH(string& foo, const_range | boost::adaptors::indirected) {
//...
}
return 0;
}