c++ error on inserting into unorderd map _ template - c++11

I am tring to insert a value into an unordered map and getting the following error:
removeduplicate.cpp:106:69: error: no matching function for call to ‘make_pair(int&, int)’
/usr/include/c++/4.8/bits/stl_pair.h:276:5: note: template<class _T1, class _T2> constexpr std::pair<typename std::__decay_and_strip<_Tp>::__type, typename std::__decay_and_strip<_T2>::__type> std::make_pair(_T1&&, _T2&&)
make_pair(_T1&& __x, _T2&& __y)
/usr/include/c++/4.8/bits/stl_pair.h:276:5: note: template argument deduction/substitution failed:
removeduplicate.cpp:106:69: note: cannot convert ‘temp->List<int>::node::data’ (type ‘int’) to type ‘int&&’
if ( !Storage.insert( std::make_pair< T , int >(temp->data , 1 ) .second )){
following is the code:
template < class T >class List{
private:
struct node{
T data;
node *next;
};
node* root;
std::unordered_map< T , int>Storage;
public:
List():root( NULL){}
~List(){}
node *getNode( T);
bool insertNode();
bool traverseList();
int removeDuplicate();
};
the following is the method---
template< class T > int List<T>::removeDuplicate(){
node * temp;
node* prev;
prev = NULL;
temp = root;
typename std::unordered_map< T , int>::iterator it;
int returnVal;
returnVal = 0;
while ( temp ){
it =Storage.find( temp->data );
if ( it != Storage.end() ){
prev->next = temp->next;
returnVal ++;
}
else{
the following line throwing error.
if ( !Storage.insert( std::make_pair< T , int >(temp->data , 1 ) .second )){
std::cerr<<"Could'nt able to inser in std::unordered_map< T , int>]n"<<std::endl;
returnVal = -9999;
}
}
prev = temp;
temp= temp->next;
}
return returnVal;
}

a map of int& can't be made, and your code is asking the compiler to do that. Try replacing
std::unordered_map< T , int>Storage;
with:
std::unordered_map< std::remove_reference<T>::type , int>Storage;
or change the declaration of getNode as such:
node* getNode(const T&);

Related

my code creates undifined behaviour when I remove cout<<endl;

this is my header
/**
* Title: Trees
* Description: NgramTree class to count and store ngrams in a given string
*/
#ifndef NGRAMTREE_H
#define NGRAMTREE_H
#include <iostream>
#include <string>
using namespace std;
typedef string TreeItemType;
struct TreeNode {
TreeItemType item;
TreeNode *leftChildPtr, *rightChildPtr;
int count;
};
// NgramTree.h
class NgramTree {
public:
NgramTree();
~NgramTree();
void addNgram( string ngram );
int getTotalNgramCount();
bool isComplete();
bool isFull();
bool isFull(TreeNode* curr);
void generateTree( string fileName, int n );
ostream& print_recursive( ostream &out, TreeNode *curr );
ostream& print( ostream &out );
private:
// ...
TreeNode *root;
friend ostream& operator<<( ostream& out, NgramTree &tree );
void destroyTree(TreeNode *& treePtr);
int getTotalNgramCount(TreeNode *node);
};
#endif
this is the cpp
/**
* Title: Trees
* Assignment: 2
* Description: implementation of NgramTree class
*/
#include "NgramTree.h"
//empty constructor
NgramTree::NgramTree():root(NULL){};
//destructor
NgramTree::~NgramTree(){
destroyTree(root);
}
bool NgramTree::isFull(){
return isFull(root);
}
bool NgramTree::isFull(TreeNode* curr){
if(curr->leftChildPtr != NULL && curr->rightChildPtr != NULL ){
return isFull(curr->leftChildPtr) && isFull(curr->rightChildPtr);
}
// on leaf node
else if( curr->leftChildPtr == NULL && curr->rightChildPtr == NULL ){
return true;
}
else if( curr == NULL ){
return true;
}
//ever other condition
return false;
}
void NgramTree::addNgram( string ngram ){
if(root == NULL){
cout<<endl;
TreeNode *tmp = new TreeNode;
tmp->item = ngram;
tmp->count = 1;
root = tmp;
return;
}
for( TreeNode *curr = root; curr != NULL; ){
if( ngram.compare(curr->item) == 0){
curr->count++;
return;
}
else if( ngram.compare(curr->item) < 0 ){
// if the node is leaf or node has just right child we have to add ngram to the leftChildPtr
if( curr->leftChildPtr == NULL ){
TreeNode *tmp = new TreeNode;
tmp->item = ngram;
tmp->count = 1;
tmp->leftChildPtr = NULL;
tmp->rightChildPtr = NULL;
curr->leftChildPtr = tmp;
return;
}
else{
curr = curr->leftChildPtr;
}
}
else if( ngram.compare(curr->item) > 0 ){
// if the node is leaf or node has just left child we have to add ngram to //the leftChildPtr
if( curr->rightChildPtr == NULL ){
TreeNode *tmp = new TreeNode;
tmp->item = ngram;
tmp->count = 1;
tmp->leftChildPtr = NULL;
tmp->rightChildPtr = NULL;
curr->rightChildPtr = tmp;
return;
}
else{
curr = curr->rightChildPtr;
}
}
}
}
void NgramTree::generateTree( string fileName, int n ){
string s;
s = "";
//first loop to find words
for(size_t i = 0; i < fileName.length(); ++i){
if(fileName[i] != ' '){
s += fileName[i];
}
//after a word end there is a ' '
if(fileName[i] == ' ' || i == fileName.length()-1 ){
for(size_t j = 0; j <= s.length() - n; ++j ){
addNgram( s.substr(j,n) );
}
s = "";
}
}
}
int NgramTree::getTotalNgramCount(){
return getTotalNgramCount(root);
}
int NgramTree::getTotalNgramCount(TreeNode *node){
if( node != NULL){
// total count is node->count + count(leftSubTree) + count(rightSubTree)
return node->count
+ getTotalNgramCount(node->leftChildPtr)
+ getTotalNgramCount(node->rightChildPtr);
}
else{
return 0;
}
}
void NgramTree::destroyTree(TreeNode *&treePtr){
if (treePtr != NULL){
destroyTree(treePtr->leftChildPtr);
destroyTree(treePtr->rightChildPtr);
delete treePtr;
treePtr = NULL;
}
}
ostream& NgramTree::print_recursive( ostream &out, TreeNode *curr ) {
if( curr == NULL ) return out;
out<<endl;
out<<"item= "<<curr->item<<", frequency= "<<curr->count;
print_recursive(out, curr->leftChildPtr);
return print_recursive(out, curr->rightChildPtr);
}
ostream& NgramTree::print( ostream &out ){
TreeNode *tmp = root;
return print_recursive(out, tmp);
}
ostream& operator<<( ostream& out, NgramTree &tree ){
return tree.print(out);
}
int main(){
NgramTree t;
string s1 = "berkan naber";
int n1 = 3;
t.generateTree(s1, n1);
cout<<t.getTotalNgramCount();
cout<<t<<endl;
return 0;
}
when I remove cout<<endl from void NgramTree::addNgram( string ngram ) method I get undifined behaviour. I removed it and added in different line and it worked again. I also added it before the if statement and it worked again. What cout<<endl might change in method is it releated to function call stack may be? I am not even sure that the problem comes from this method? I am open to solutions that offering somthing to put instead of cout<<endl; which doesn't affect the terminal output unlike cout<<endl.

How to pass Comparator to user define Templeted class?

I want to create a generalized heap data structure, and facing an issue with passing template comparator.
template<typename T, typename C = less<T> > class Heap{
vector<T> *heap;
public:
Heap(vector<T> *arr){
heap = new vector<T> (arr->begin(), arr->end());
build_heap();
}
void build_heap(){
size_t n = heap->size();
for (size_t i=(n-1)/2; i>=0; i--){
shiftDown(i);
}
}
void shiftDown(size_t i){ /// heap logic
while(i < heap->size()){
size_t child = 2*i+1;
// int min_ind = 2*i+1;
if(child >= heap->size())
return;
if(child+1 < heap->size()){
if( C(heap->at(child+1),heap->at(child)) ){ // <----- using C as comparator
child++;
}
}
if( C(heap->at(child), heap->at(i)) ){ // <----- using C as comparator
swap(heap->at(child), heap->at(i));
i = child;
}
else
break;
}
}
};
int main(){
vector<int> v={8,7,6,5,4,3,2,1};
Heap<int, less<int> > heap(&v);
}
error
heap.cpp: In instantiation of ‘void Heap<T, C>::shiftDown(size_t) [with T = int; C = std::less<int>; size_t = long unsigned int]’:
heap.cpp:15:4: required from ‘void Heap<T, C>::build_heap() [with T = int; C = std::less<int>]’
heap.cpp:10:3: required from ‘Heap<T, C>::Heap(std::vector<_Tp>*) [with T = int; C = std::less<int>]’
heap.cpp:49:34: required from here
heap.cpp:32:9: error: no matching function for call to ‘std::less<int>::less(__gnu_cxx::__alloc_traits<std::allocator<int>, int>::value_type&, __gnu_cxx::__alloc_traits<std::allocator<int>, int>::value_type&)’
32 | if( C(heap->at(child+1),heap->at(child)) ){
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
detailed error
i'm following same syntex of declaration as stl c++ do, still i'm getting error. please help me out.
template<typename T, typename C = less<T> > class Heap;
any help or pointer to help is appreciated. thank you.
template<class T>
class Comparator{
bool operator()(const T &a, const T &b){
...
// returns logic
}
}
template<class T, class Comp >
class AnyClass{
public:
...
void function(){
// code ...
Comp<T>()(obj1, obj2);
}
...
}
calling sytex :
...
AnyClass *obj = new AnyClass<Type , Comparator>();
obj.function()
...
passing Comparator to templated class and when we need to compare objects
we create a functional object and call operator() with args to compare.
In question, that object is less<int>.
Comp<T>()(obj1, obj2);

How to return nullptr from a lambda function?

I have a small lambda function which shall find and return a QTreeWidgetItem. But if it does not find the given item, then it shall return a nullptr. But if I try to compile it then it gives me an error.
The function:
auto takeTopLevelItem = []( QTreeWidget* aTreeWidget, const QString& aText )
{
const int count = aTreeWidget->topLevelItemCount();
for ( int index = 0; index < count; ++index )
{
auto item = aTreeWidget->topLevelItem( index );
if ( item->text( 0 ) == aText )
{
return aTreeWidget->takeTopLevelItem( index );
}
}
return nullptr; // This causes a compilation error.
};
The error:
Error 1 error C3487: 'nullptr': all return expressions in a lambda must have the same type: previously it was 'QTreeWidgetItem *' cpp 251
I changed the mentioned line with this and now it compiles:
return (QTreeWidgetItem*)( nullptr );
but I would like to avoid this syntax. How can I solve this ?
I use Visual Studio 2012.
You can add an explicit return type annotation:
auto takeTopLevelItem = []( ... ) -> QTreeWidgetItem*
{
// ...
}
That way nullptr will be converted to your pointer type properly. You're getting that error because the lambda assumes no conversions should be made, and treats nullptr_t as a legitimate alternative return type.
As a side note, consider using (std::)optional instead. The nullability of pointers can be used to represent a missing return, but it doesn't mean it necessarily should be.
If you just want to avoid the syntax, rather than the casting, you could it like this:
static_cast<QTreeWidgetItem*>(nullptr);
I made a small example, on how Bartek's and mine's answer really work:
#include <iostream>
class A {
int a;
};
auto bla = [] (A* obj, bool flag) -> A* {
if(flag)
return obj;
return nullptr;
// return static_cast<A*>(nullptr);
};
int main() {
A obj;
A* ptr = &obj;
bool flag = false;
if( bla(ptr, flag) == nullptr)
std::cout << "ok\n";
return 0;
}
I had this very same issue with some Smart Pointers, so I found I could do this to avoid the issue:
auto myFunc= [](MyClass* class)
{
MyPointer* pointer = nullptr;
if( class && class->isValid() )
{
pointer = class->getPointerInstance()
}
return pointer;
}
Similarly, for shared pointer, just repleace MyPointer* by std::shared_ptr<MyPointer>.
So your code would looks like:
auto takeTopLevelItem = []( QTreeWidget* aTreeWidget, const QString& aText )
{
QTreeWidgetItem* item = nullptr;
const int count = aTreeWidget->topLevelItemCount();
for ( int index = 0; index < count; ++index )
{
auto item = aTreeWidget->topLevelItem( index );
if ( item->text( 0 ) == aText )
{
item = aTreeWidget->takeTopLevelItem( index );
break;
}
}
return item;
};

how would I go about handling these return type errors? (hashmap/table)

#ifndef HASHMAP_H
#define HASHMAP_H
#include <iostream>
#include <string>
#include <vector>
using namespace std;
enum Status{open , active, deactivated };
//template <typename T>
template</*typename Key,*/ typename T>
class hashmap{
private:
class Node{
public:
const string Key;
//vector<T> values;
T value;
Status status;
Node(string key, T val) :Key(key), value(val), status(active){}
void operator =(const Node &n){
string *ptr;
ptr = (string*)(&(this->Key));
*ptr = n.Key;
//Node(n);
this->status = n.status;
this->value = n.value;
}
Node() :status(open){}
Node(const string& key) :Key(key), status(active){}
//Node(const Node &n) : value(n.val), status(n.status){}
};
//typedef map<
unsigned int hash(const string& s, int tableSize){
unsigned int h = 0;
/*each(s)*/
for(auto it : s) h = 31 * h + unsigned(it);
return h % tableSize;
}
unsigned int hash(const string& s){
return hash(s, table_size);
}
int table_size = 103;
vector<Node> table;
typedef typename vector<Node>::iterator iter;
public:
//default constructor
hashmap(){
table = vector<Node>(table_size);
}
//copy constructor
hashmap(const hashmap& x){
table = x.table;
//for (auto it = )
}
//assignment operator //has been removed
hashmap& operator=(const hashmap& x){
this->table.erase(this->table.begin(), this->table.begin() + 103);
for ( int i = 0; i < x.table_size; i++){
this->table.push_back(x.table.at(i));
}
return *this;
}
//destructor
~hashmap(){
table.clear();
}
//index operator
T& operator[](const string x){
int h = hash(x, table.size());
if (table[h].Key == x){
return (table[h].value);
}
else {
Node* n = new Node(x);
table[h] = *n;
return (table[h].value);
}
}
//Node test
void okay(const string x,int i){
Node *temp = new Node(x, i);
cout << temp->status << endl;
/*cout << table[1].status << endl;
cout << table[2].status << endl;
table.at(0) = (*temp);
cout << table[0].Key << endl;
cout << table[0].value << endl;
cout << table[3].status << endl;*/
}
int stride(int x){
return (7-x%7);
}
//find()
iter find(const string& x){
int h = hash(x);
int s = stride(h);
int t = table_size;
int z;
//for (int i = 0; i < t; i++){
for (int i = hash(x, table_size) % t; i != t; i = (i + stride(h)) % t){
z = (h + i*s) % table_size;
if (table[z].status == open) return NULL;
if (table[z].status == deactivated) continue;
if (table[z].Key == x) return &table[h];
}
return table.end();
}
//begin()
iter begin(){
return table.begin();
}
//end()
iter end(){
return table.end();
}
};
#endif // !HASHMAP_H
Everything seems to be working fine except the find function. It's suppose to probe through the vector and return values upon conditions but the problem I'm having is I get these errors about return type conflicts.
Error2error C2664: 'std::_Vector_iterator<std::_Vector_val<std::_Simple_types<hashmap::Node>>>::_Vector_iterator(const
std::_Vector_iterator<std::_Vector_val<std::_Simple_types<hashmap::Node>>> &)' : cannot convert argument 1 from 'hashmap<int>::Node *' to 'const
std::_Vector_iterator<std::_Vector_val<std::_Simple_types<hashmap<int>::Node>>> &'
Error1error C2664: 'std::_Vector_iterator<std::_Vector_val<std::_Simple_types<hashmap<int>::Node>>>::_Vector_iterator(const
std::_Vector_iterator<std::_Vector_val<std::_Simple_types<hashmap<int>::Node>>> &)' : cannot convert argument 1 from 'int' to 'const
std::_Vector_iterator<std::_Vector_val<std::_Simple_types<hashmap<int>::Node>>> &'
How can I edit the iterator to fix this?
thank you.

Is there a way to find the C++ mangled name to use in GetProcAddress?

The common "solution" to use GetProcAddress with C++ is "extern "C", but that breaks overloading. Name mangling allows multiple functions to co-exist, as long as their signature differs. But is there a way to find these mangled names for GetProcAddress?
The VC++ compiler knows its own name mangling scheme, so why not use that? Inside template<typename T> T GetProcAddress(HMODULE h, const char* name), the macro __FUNCDNAME__ contains the mangled name of GetProcAddress. That includes the T part. So, inside GetProcAddress<void(*)(int), we have a substring with the mangled name of void(*)(int). From that, we can trivially derive the mangled name of void foo(int);
This code relies on the VC++ macro __FUNCDNAME__. For MinGW you'd need to base this on __PRETTY_FUNCTION__ instead.
FARPROC GetProcAddress_CppImpl(HMODULE h, const char* name, std::string const& Signature)
{
// The signature of T appears twice in the signature of T GetProcAddress<T>(HMODULE, const char*)
size_t len = Signature.find("##YA");
std::string templateParam = Signature.substr(0, len);
std::string returnType = Signature.substr(len+4);
returnType.resize(templateParam.size()); // Strip off our own arguments (HMODULE and const char*)
assert(templateParam == returnType);
// templateParam and returnType are _pointers_ to functions (P6), so adjust to function type (Y)
std::string funName = "?" + std::string(name) + "##Y" + templateParam.substr(2);
return ::GetProcAddress(h, funName.c_str());
}
template <typename T>
T GetProcAddress(HMODULE h, const char* name)
{
// Get our own signature. We use `const char* name` to keep it simple.
std::string Signature = __FUNCDNAME__ + 18; // Ignore prefix "??$GetProcAddress#"
return reinterpret_cast<T>(GetProcAddress_CppImpl(h, name, Signature));
}
// Showing the result
struct Dummy { };
__declspec(dllexport) void foo( const char* s)
{
std::cout << s;
}
__declspec(dllexport) void foo( int i, Dummy )
{
std::cout << "Overloaded foo(), got " << i << std::endl;
}
__declspec(dllexport) void foo( std::string const& s )
{
std::cout << "Overloaded foo(), got " << s << std::endl;
}
__declspec(dllexport) int foo( std::map<std::string, double> volatile& )
{
std::cout << "Overloaded foo(), complex type\n";
return 42;
}
int main()
{
HMODULE h = GetModuleHandleW(0);
foo("Hello, ");
auto pFoo1 = GetProcAddress<void (*)( const char*)>(h, "foo");
// This templated version of GetProcAddress is typesafe: You can't pass
// a float to pFoo1. That is a compile-time error.
pFoo1(" world\n");
auto pFoo2 = GetProcAddress<void (*)( int, Dummy )>(h, "foo");
pFoo2(42, Dummy()); // Again, typesafe.
auto pFoo3 = GetProcAddress<void (*)( std::string const& )>(h, "foo");
pFoo3("std::string overload\n");
auto pFoo4 = GetProcAddress<int (*)( std::map<std::string, double> volatile& )>(h, "foo");
// pFoo4 != NULL, this overload exists.
auto pFoo5 = GetProcAddress<void (*)( float )>(h, "foo");
// pFoo5==NULL - no such overload.
}
Use dumpbin /exports 'file.dll' to get the decorated / undecorated name of all the symbols.
It's impossible to do it just by using GetProcAddress. However, one way to do it would be to enumerate all the exported functions for that particular module, and do a pattern matching to find all the mangled names.
More specifically, refer to this answer here. The only change you will need to make would be to pass in TRUE for MappedAsImage parameter and the return value of GetModuleHandle for Base parameter to ImageDirectoryEntryToData function call.
void EnumerateExportedFunctions(HMODULE hModule, vector<string>& slListOfDllFunctions)
{
DWORD *dNameRVAs(0);
_IMAGE_EXPORT_DIRECTORY *ImageExportDirectory;
unsigned long cDirSize;
_LOADED_IMAGE LoadedImage;
string sName;
slListOfDllFunctions.clear();
ImageExportDirectory = (_IMAGE_EXPORT_DIRECTORY*)
ImageDirectoryEntryToData(hModule,
TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &cDirSize);
if (ImageExportDirectory != NULL)
{
dNameRVAs = (DWORD *)ImageRvaToVa(LoadedImage.FileHeader,
LoadedImage.MappedAddress,
ImageExportDirectory->AddressOfNames, NULL);
for(size_t i = 0; i < ImageExportDirectory->NumberOfNames; i++)
{
sName = (char *)ImageRvaToVa(LoadedImage.FileHeader,
LoadedImage.MappedAddress,
dNameRVAs[i], NULL);
slListOfDllFunctions.push_back(sName);
}
}
}
I can't quite fathom why you'd ever want/need a constexpr version of MSalters' solution, but here it is, complete with namespace mangling. Use as
using F = int(double*);
constexpr auto f = mangled::name<F>([]{ return "foo::bar::frobnicate"; });
constexpr const char* cstr = f.data();
where F is the function signature and foo::bar::frobnicate is the (possibly qualified) name of the function.
#include<string_view>
#include<array>
namespace mangled
{
namespace detail
{
template<typename F>
inline constexpr std::string_view suffix()
{
auto str = std::string_view(__FUNCDNAME__);
return str.substr(14, str.size() - 87);
}
template<typename L>
struct constexpr_string
{
constexpr constexpr_string(L) {}
static constexpr std::string_view data = L{}();
};
template<typename Name>
inline constexpr int qualifiers()
{
int i = -2, count = -1;
while(i != std::string_view::npos)
{
i = Name::data.find("::", i + 2);
count++;
}
return count;
}
template<typename Name>
inline constexpr auto split()
{
std::array<std::string_view, qualifiers<Name>() + 1> arr = {};
int prev = -2;
for(int i = arr.size() - 1; i > 0; i--)
{
int cur = Name::data.find("::", prev + 2);
arr[i] = Name::data.substr(prev + 2, cur - prev - 2);
prev = cur;
}
arr[0] = Name::data.substr(prev + 2);
return arr;
}
template<typename F, typename Name>
struct name_builder
{
static constexpr auto suf = detail::suffix<F>();
static constexpr auto toks = split<Name>();
static constexpr auto len = Name::data.size() + suf.size() - toks.size() + 6;
static constexpr auto str = [] {
std::array<char, len> arr = {};
arr[0] = '?';
int i = 1;
for(int t = 0; t < toks.size(); t++)
{
if(t > 0)
arr[i++] = '#';
for(auto c : toks[t])
arr[i++] = c;
}
arr[i++] = '#';
arr[i++] = '#';
arr[i++] = 'Y';
for(auto c : suf)
arr[i++] = c;
return arr;
}();
};
}
template<typename F, typename LambdaString>
inline constexpr std::string_view name(LambdaString)
{
using Cs = detail::constexpr_string<LambdaString>;
using N = detail::name_builder<F, Cs>;
return {N::str.data(), N::len};
}
}
GodBolt

Resources