Index with boost multi_index - boost

How can I index a boost::multi_index container using a member function of class(that is being stored in the multi_index) that returns a constant reference of another class?
The error I get is :
error C2440: 'specialization' : cannot convert from 'overloaded-function' to 'RetClass (__thiscall StoreMe::* )(void) const'
Edit1:
This is a complete verifiable piece of similar code I created which has the same error,
#include "stdafx.h"
#include<multi_index_container.hpp>
#include<boost/multi_index/hashed_index.hpp>
#include<boost/multi_index/mem_fun.hpp>
class RetClass
{
int a, b;
};
class StoreMe
{
RetClass ex;
public:
void setId(RetClass a) {
ex = a;
};
virtual const RetClass& getId() const { return ex; }
};
typedef boost::multi_index_container<
StoreMe,
boost::multi_index::indexed_by<
boost::multi_index::hashed_non_unique<boost::multi_index::const_mem_fun<StoreMe, RetClass, &StoreMe::getId> >
>
> mi_storeMe;
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
TIA
-R

Use boost::multi_index::const_mem_fun.
Edited after OP's additional information: the return type specified in const_mem_fun has to be exactly the same as that of the function you want to use for indexing. Note the differences in your current code:
virtual const RetClass& getId() const;
const_mem_fun<StoreMe, RetClass, &StoreMe::getId>
So, change the const_mem_fun part as follows:
const_mem_fun<StoreMe, const RetClass&, &StoreMe::getId>

Related

Sorting vector of objects c++ raise C2280 error

I have a vector of Workout objects, and I want to sort it by the prices of the workout (each Workout have const field price and getPrice function)
When Im trying to sort the array i get a C2280 error -
Workout &Workout::operator =(const Workout &)': attempting to reference a deleted function
#ifndef WORKOUT_H_
#define WORKOUT_H_
#include <string>
class Workout {
public:
Workout(int w_id, std::string w_name, int w_price, WorkoutType w_type);
int getPrice() const;
Workout& operator =(const Workout& other)
{
if (this == &other) return *this;
return *new(this) Workout(other.getId(), other.getName(),
other.getPrice(), other.getType());
}
private:
const int price;
};
I else have virtual class Customer and cheapCustomer object that inheritence from it, and function- order(const std::vector& workout_options) that needs to sort the vector by the prices.
Here is the Customer cpp file -
#include "Customer.h"
#include <algorithm>
using namespace std;
Customer::Customer(std::string c_name, int c_id) :name(c_name), id(c_id)
{
}
CheapCustomer::CheapCustomer(std::string name, int id) :Customer(name, id)
{
}
std::vector<int> CheapCustomer::order(const std::vector<Workout>& workout_options)
{
std::vector<int>* v = new std::vector<int>();
std::vector<Workout> tmp = workout_options;
std::sort(tmp.begin(), tmp.end(), [](const Workout& w1, const Workout& w2) {
return w1.getPrice() < w2.getPrice();
});
return *v;
//delete v
}
#include <vector>
#include "Customer.h"
#include "Trainer.h"
#include <algorithm>
using namespace std;
int main(int argc, char** argv) {
Workout w1 = Workout(1, "w1", 10, CARDIO);
Workout w2 = Workout(2, "w2", 20, CARDIO);
Workout w3 = Workout(3, "w3", 30, MIXED)
std::vector<Workout> v;
v.push_back(w1);
v.push_back(w2);
v.push_back(w3);
Customer* c_cheap = new CheapCustomer("Cheap", 20);
vector<int> order_cheap = c_cheap->order(v);
can some one please tell me how to fix it?
Thank you so much
I tried to use unique_ptr and still the same error-
C2280 'std::unique_ptr<Workout,std::default_delete>::unique_ptr(const std::unique_ptr<Workout,std::default_delete> &)': attempting to reference a deleted function
std::vector<int> CheapCustomer::order(const std::vector<Workout>& workout_options)
{
vector<int>* v = new std::vector<int>();
vector<unique_ptr<Workout>> v_unique_ptr;
for (Workout workout : workout_options) {
v_unique_ptr.push_back(unique_ptr<Workout>(new Workout(workout.getId(),workout.getName(),workout.getPrice(),workout.getType())));
}
std::sort(v_unique_ptr.begin(), v_unique_ptr.end(), [](unique_ptr<Workout> w1, unique_ptr<Workout> w2) {
return w1->getPrice() < w2->getPrice();
});
}
Edited:
its worked here
vector<int>* v = new std::vector<int>();
vector<unique_ptr<Workout>> v_unique_ptr;
for (Workout workout : workout_options) {
v_unique_ptr.push_back(move(unique_ptr<Workout>(new Workout(workout.getId(),workout.getName(),workout.getPrice(),workout.getType()))));
}
std::sort(v_unique_ptr.begin(), v_unique_ptr.end(), [](unique_ptr<Workout>& w1, unique_ptr<Workout>& w2) {
return w1->getPrice() < w2->getPrice();
});
v->push_back(v_unique_ptr[0]->getId());
return *v;
Thank you so much
In order to use std::sort, the element type needs to be move-assignable. Your element type isn't, because of all the const data members.
So you may either:
Remove the const
Provide your own move assignment operator that somehow gets around const
Don't place Workout objects in a container, place pointers instead (preferably smart pointers such as unique_ptr).

Hash table of templated functor

I want to create a hastable to member templated functor, I explain.
Here is my exemple which does'nt work:
#include <iostream>
#include <unordered_map>
using namespace std;
class MyFirstClass
{
int i_;
public:
MyFirstClass(): i_(0) {}
void setI(int i) { i_ = i; }
int getI() { return i_; }
};
class MySecondClass
{
bool b_;
public:
MySecondClass(): b_(0) {}
void setB(bool b) { b_ = b; }
bool getB() { return b_; }
};
template<class X, void (X::*p)()>
class MyFunctor
{
X& _x;
public:
MyFunctor(X& x) : _x( x ) {}
void operator()() const { (_x.*p)(); }
};
int main(int argc, char *argv[])
{
unordered_map<string,MyFunctor> myHashTable;
MyFirstClass first;
MyFirstClass second;
myHashTable["int"] = first::setI;
myHashTable["bool"] = second::setB;
//
string key = "bool";
int value = 1;
myHashTable[key](value);
return 0;
}
I have multiple class with their own setter . I would like to be able thanks to the has table and a command {string,int} change the value of the corresponding class.
The previous code is not working for the moment and I am stuck.
There are a few problems with your code, as it stands.
Firstly, from your example unordered_map<string,MyFunctor> doesn't name a type, because MyFunctor doesn't name a type. You could create a non-template base class with a virtual operator(), and then have MyFunctor inherit from it.
Second, you aren't using compatible method pointers, MyFirstClass::setI and MySecondClass::setB both take a parameter.
Third, related to the first, you have to specify the template parameters when constructing an object from a class template. (until c++17's class template deduction guides). You also have ungrammatical syntax that I assume is trying to specify the object argument to the MyFunctor constructor alongside the method-pointer template argument.
You would have something like
class MyFunctorBase {
virtual void operator()(void * i) const = 0;
}
template<class T, class X, void (X::*p)(T)>
class MyFunctor : public MyFunctorBase
{
X& _x;
public:
MyFunctor(X& x) : _x( x ) {}
void operator()(void * i) const override { (_x.*p)(*static_cast<T*>(i)); }
};
int main(int argc, char *argv[])
{
unordered_map<string,shared_ptr<MyFunctorBase>> myHashTable;
MyFirstClass first;
MyFirstClass second;
myHashTable["int"] = make_shared<MyFunctor<int, MyFirstClass, &MyFirstClass::setI>>(first);
myHashTable["bool"] = make_shared<MyFunctor<bool, MySecondClass, &MySecondClass::setB>>(second);
//
string key = "bool";
bool value = true;
(*myHashTable[key])(static_cast<void *>(&value));
return 0;
}
Or, much more easily, use the existing std::function, which does that for you
int main(int argc, char *argv[])
{
unordered_map<string,function<void(void *)>> myHashTable;
MyFirstClass first;
MyFirstClass second;
myHashTable["int"] = [first](void * i) { first.setI(*static_cast<int *>(i)); };
myHashTable["bool"] = [second](void * i) { second.setB(*static_cast<bool *>(i)); };
//
string key = "bool";
bool value = true;
myHashTable[key](static_cast<void *>(&value));
return 0;
}

Convert "Tcl_Obj* const objv[]" to "char** argv"

I'm using Tcl 8.6 and I'm trying to do something like this to add functions to the tcl interpreter
Tcl_Interp* interp,
void init() {
interp = Tcl_CreateInterp();
}
void add_tcl_function(char* cmd, function<int(int,char**)> F) {
obj2argv* o2a = new obj2argv;
auto lambda_proc = [&](
ClientData cdata,
Tcl_Interp* interp,
int objc,
Tcl_Obj* const objv[])
{
o2a->set(objc, objv);
F(objc, o2a->get_argv());
};
auto lamba_delete = [&](
delete o2a;
};
Tcl_CreateObjCommand(interp, cmd, lamda_proc, NULL, lamda_delete);
}
What I'm wondering is how to convert "Tcl_Obj* const objv[]" to "char** argv"?
I was thinking about creating a class:
class obj2argv {
obj2argv();
void set(int objc, Tcl_Obj* const objv[]);
char** get_argv();
private:
//...
};
any ideas on how to implement set() and get_argv()?
Is there an easier way to do this?
Thanks.
obj2argv* o2a = new obj2argv;
If you're interfacing a function that's fundamentally working with const char** for arguments, you should register the function with Tcl_CreateCommand and let Tcl handle the mapping to strings for you. It already has all the mechanisms required.
More formally, you are dealing with a gluing function with this signature:
typedef int (Tcl_CmdProc) (ClientData clientData, Tcl_Interp *interp,
int argc, CONST84 char *argv[]);
The CONST84 should be read as being plain const in all new code, and ClientData is a pointer-sized value that Tcl just hands around and never inspects (same as with your existing code).
If you are going to do the mapping yourself, Tcl_GetString takes a Tcl_Obj* and returns the char* representation of it. The representation should be usually treated as const; it simply isn't formally typed as such for historical reasons.
I wanted to add some more information:
I gave up on using lambda's because when I added capture list it won't convert the lambda to a function pointer for some reason. So I went with the traditional approach (see below). EXCEPT: I still have not idea why the TCL document says
typedef int Tcl_CmdProc(
ClientData clientData,
Tcl_Interp *interp,
int argc,
const char *argv[]);
But the compiler requires this to compile:
typedef int Tcl_CmdProc(
ClientData clientData,
Tcl_Interp *interp,
int argc,
Tcl_Obj* const* argv);
The Code:
int cmd_dispatch(
ClientData clientData,
Tcl_Interp* interp,
int argc,
Tcl_Obj* const* argv)
{
function<int(int,char**)> F = *(function<int(int,char**)>*)clientData;
return F(argc, (char**) argv); // <= CAST DOESN'T SEEM RIGHT
}
void cmd_delete(ClientData clientData)
{
}
void add_tcl_function(const char* cmd, function<int(int,char**)> F) {
Tcl_CreateObjCommand(interp, cmd, cmd_dispatch, (void*)&F, cmd_delete);
}
VERSION 2:
struct cmd_data {
//Tcl_Interp* interp,
function<int(int,char**)> F;
int argc;
char* argv[MAX_ARGS];
};
int cmd_dispatch(
ClientData clientData,
Tcl_Interp* interp,
int argc,
Tcl_Obj* const* objv)
{
auto cmd_data1 = (struct cmd_data*) clientData;
cmd_data1->argc = argc;
for(int i=0; ((i < argc) && (i < MAX_ARGS)); i++) {
cmd_data1->argv[i] = Tcl_GetString(objv[i]);
// Who owns object returned by Tcl_GetString?
// memory leak? or invalid after return from function?
// garbage collected by tcl interp?
}
return cmd_data1->F(argc, cmd_data1->argv);
}
void cmd_delete(ClientData clientData)
{
auto cmd_data1 = (struct cmd_data*) clientData;
if (cmd_data1) {
delete cmd_data1;
}
}
void add_tcl_function(const char* cmd, function<int(int,char**)> F) {
auto cmd_data1 = new struct cmd_data;
cmd_data1->F = F;
Tcl_CreateObjCommand(interp, cmd, cmd_dispatch, (void*)cmd_data1, cmd_delete);
}
void init_tcl_commands() {
auto lambda_hello = [&](int argc ,char** argv) -> int {
cout << "HELLO WORLD!\n";
return 0;
};
tcl_backend::add_tcl_function("hello", lambda_hello);
}

VStudio 2012 Create custom allocator for container of move-only type

I am trying to create an stl container of a move-only type that uses its own allocator in VStudio 2012.
The trouble is: it seems as though I have to provide a construct function for the allocator which in turn needs access to a public copy constructor on the contained type.
I either get:
error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'
or
error C2039: 'construct' : is not a member of 'MyAllocator'
The same code works in clang so I suspect the problem is due to Microsoft but can anyone suggest a possible work around?
This is my code for minimal reproduction
#include <memory>
#include <vector>
using namespace std;
template< typename T>
struct MyAllocator
{
typedef T value_type;
typedef value_type* pointer;
typedef value_type& reference;
typedef const value_type* const_pointer;
typedef const value_type& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
template<class t_other>
struct rebind
{
typedef MyAllocator<t_other> other;
};
MyAllocator():m_id(0) {}
MyAllocator(int id):m_id(id){}
template <class T>
MyAllocator(const MyAllocator<T>& other)
:m_id(other.getId())
{
}
T* allocate(std::size_t n)
{
return reinterpret_cast<T*>(malloc(sizeof(T) * n));
}
void deallocate(T* p, std::size_t n)
{
free(p);
}
int getId() const{ return m_id;}
//Have to add these although should not be necessary
void construct(pointer mem, const_reference value)
{
std::_Construct(mem, value);
}
void destroy(pointer mem)
{
std::_Destroy(mem);
}
private:
int m_id;
};
template <class T1, class U>
bool operator==(const MyAllocator<T1>& lhs, const MyAllocator<U>& rhs)
{
return lhs.getId() == rhs.getId() ;
}
template <class T1, class U>
bool operator!=(const MyAllocator<T1>&, const MyAllocator<U>&)
{
return lhs.getId() != rhs.getId();
}
//define a move only type
typedef unique_ptr<uint32_t> MyIntPtr;
//define a container based on MyIntPtr and MyAllocator
typedef vector<MyIntPtr, MyAllocator<MyIntPtr> > MyVector;
int main(int argc, char* argv[])
{
MyAllocator<MyIntPtr> alloc1(1);
MyVector vec(alloc1);
uint32_t* rawPtr = new uint32_t;
*rawPtr = 18;
vec.emplace_back(rawPtr);
return 0;
}
The error you get is because you try to construct a std::unique_ptr from a constant reference to a std::unique_ptr of the same type - and there is no such constructor.
You can rework your construct method to take an an rvalue reference and then everything compiles nicely:
void construct(pointer mem, value_type&& value)
{
std::_Construct(mem, std::move(value));
}

Error during cast of an object to std::string with proper operator-overloading

Follwing short programm will run perfect with VS 2013 and reach the marked point. But in XCode the compiler will show an error due ambiguous constructor. How to work around?
#include <iostream>
#include <string>
class atest
{
public:
explicit operator const char *()
{
return "";
}
template<class T> operator T()
{
}
operator std::string()
{
return std::string("Huhuhu");
}
template<class T> atest &operator =(T value)
{
}
atest &operator =(const std::string &value)
{
return *this; // I want to reach this point
}
};
int main(int argc, char* argv[])
{
atest tst;
// auto a = (std::string)tst;
std::string astr;
// do some stuff
astr=tst; // I wanna keep this line
return 0;
}
Clang is not able to distinguish between different constructor where VS2013 is taking the right one. I search now for a way to exclude the "const char *" template of the assignment operator.
std::string have multiple constructors taking single arguments, and since you provide both a conversion operator for std::string and a generic any-type conversion operator, the compiler simply don't know which constructor to pick.
I think you have written far too many overloaded functions. The only function you need is this:
operator std::string()
{
return std::string("Huhuhu");
}
Comment rest all and your code would work just fine.

Resources