Is there a nicer way of doing this
auto commodityOneLeg = boost::bind(&VegaFactory::load_commodity_one_leg,this,conn,_1);
std::map<std::string,decltype(commodityOneLeg)> methods;
methods.insert(std::make_pair("COMMODITYONELEG",commodityOneLeg));
methods.insert(std::make_pair("FXOPTION",boost::bind(&VegaFactory::load_fx_index,this,conn,_1)));
methods.insert(std::make_pair("FXBARROPT",boost::bind(&VegaFactory::load_fx_bar_opt,this,conn,_1)));
methods.insert(std::make_pair("COMMODITYINDEX",boost::bind(&VegaFactory::load_fx_index,this,conn,_1)));
auto f = methods.find(trade_table);
if(f != methods.end()) {
fx_opt = (f->second)(t_id);
}
Is there a way of declaring the type of std:map<> without having to declare a mapping first on the previous line? I guess I mean aesthetically - Code should look neat right?
Is there a cleaner/simpler way to do this c++ string switch statement overall when the input is a 'trade type' string.
Edit
To clarify further. I can manually write out the type of the boost:bind type but that seems excessive. And this is probably a really good example of where auto and decltype can be used to simplify the code.
However having to declare one entry in the map one way and the others in a different way just looks wrong; so that's what I want to address
IMHO using Boost.Signals2 is a more clear way. There is also the Boost.Signals library but it is deprecated starting from Boost 1.54. The following code demonstrates it. I think something similar is possible to implement using the Boost.Function library too.
#include <boost/signals2.hpp>
#include <map>
#include <string>
typedef boost::signals2::signal<bool (int)> CSignal;
typedef CSignal::slot_type CSignalSlotType;
typedef std::map<std::string, CSignalSlotType> CMethodMap;
bool Func1(int a, int b) {
return a == b;
}
bool Func2(int a, int b) {
return a < b;
}
int main(int, char *[]) {
CMethodMap methods;
methods.insert(std::make_pair("Func1", boost::bind(&Func1, 1, _1)));
methods.insert(std::make_pair("Func2", boost::bind(&Func2, 2, _1)));
auto it = methods.find("Func1");
if(it != methods.end()) {
CSignal signal;
signal.connect(it->second);
auto rt = signal(2);
if (rt) {
const bool result = *rt;
}
}
return 0;
}
Here is a sample code using the Boost.Function. It looks even simpler but I used to use the Signals2 library.
#include <map>
#include <string>
#include <boost/function.hpp>
#include <boost/bind.hpp>
typedef boost::function<bool (int)> CFunction;
typedef std::map<std::string, CFunction> CMethodMap;
bool Func1(int a, int b) {
return a == b;
}
bool Func2(int a, int b) {
return a < b;
}
int main(int, char *[]) {
CMethodMap methods;
methods.insert(std::make_pair("Func1", boost::bind(&Func1, 1, _1)));
methods.insert(std::make_pair("Func2", boost::bind(&Func2, 2, _1)));
auto it = methods.find("Func1");
if(it != methods.end()) {
auto &f = it->second;
const bool result = f(2);
}
return 0;
}
Related
The question is within the code snippet:
#include <algorithm>
#include <utility>
#include <iostream>
struct A {
static int max(std::pair<int, int> const& pair) {
return std::max(pair.first, pair.second);
}
int use_max(std::pair<int, int> const & p, int const i) {
// 1) The following works fine:
// return std::max(i, max(p));
// 2) The following also works fine:
// using std::max;
// return max(i, this->max(p));
// 3) This does not compile, afaiu cause the A::max did
// not even got into the overload resolution list due to
// name look up rules.
using std::max;
return max(i, max(p));
// Question: What do I write here to add A::max into the
// overload resolution list, e.g., something like:
// using std::max;
// using A::max;
// return max(i, max(p));
}
};
int main() {
std::cout << A().use_max(std::make_pair(2, 3), 1);
}
using A::max; is not possible since A is a class and not a namespace.
And the answer to your query is simple:
return max(i, A::max(p));
I am not sure what else are you hoping to achieve here.
Update: Thought about it some more and you can modify code this way?
#include <algorithm>
#include <utility>
#include <iostream>
struct B {
static int max(int A, int B)
{
return std::max(A,B);
}
};
struct A:B{
static int max(std::pair<int, int> const& pair) {
return std::max(pair.first, pair.second);
}
using B::max;
int use_max(std::pair<int, int> const & p, int const i) {
return max(i, max(p));
}
};
int main() {
std::cout << A().use_max(std::make_pair(2, 3), 1);
}
I am trying to learn boost::phoenix and trying to use it in std::transform like below.
class myClass
{
int i;
public:
getNumber();
setNumber(int j);
};
int main()
{
std::vector<myClass*> vect
std::vector<int> numVect
numVect.resize(vect.size());
using boost::phoenix::arg_names::arg1;
std::transform (vect.begin(), vect.end(), numVect.begin(), arg1->getNumber());
}
But, I am getting an error error: base operand of '->' has non-pointer type 'const boost::phoenix::actor<boost::phoenix::argument<0> >'
I am not really sure what does it mean. Any help would be great. Thanks
As you note above, the way to do this with Phoenix is with phoenix::bind or with ->* as you do above:
#include <vector>
#include <boost/phoenix/core.hpp>
#include <boost/phoenix/operator.hpp>
#include <boost/range/algorithm/transform.hpp>
class myClass
{
int i;
public:
int getNumber() { return i; }
void setNumber(int j) { i = j; }
};
int main()
{
std::vector<myClass*> vect;
std::vector<int> numVect;
using boost::phoenix::arg_names::arg1;
boost::transform(vect,
std::back_inserter(numVect),
(arg1->*&myClass::getNumber)());
}
Phoenix can be complicated, and bind expressions are some of the most convoluted and contrived of Phoenix's syntactic contortions, but in all honestly, this one doesn't seem that bad.
C++14's polymorphic lambdas will obviate much of Phoenix, by the way.
I'd use
std::transform (vect.begin(), vect.end(), numVect.begin(), phx::bind(&myClass::getNumber, arg1));
Or, if you wanted nicer syntax:
auto getNumber = phx::lambda [ phx::bind(&myClass::getNumber, arg1) ];
std::transform (vect.begin(), vect.end(), numVect.begin(), getNumber(arg1));
Demo:
#include <vector>
#include <algorithm>
#include <iostream>
#include <boost/phoenix/phoenix.hpp>
namespace phx = boost::phoenix;
struct myClass
{
int i;
int getNumber() const { return i; }
void setNumber(int j) { i = j; }
};
using namespace boost::phoenix::arg_names;
static const auto getNumber = phx::lambda [ phx::bind(&myClass::getNumber, arg1) ];
int main()
{
const std::vector<myClass*> vect { new myClass{1}, new myClass{2}, new myClass{42} };
std::vector<int> numVect(vect.size());
// puritan/standard version:
std::transform (vect.begin(), vect.end(), numVect.begin(), std::mem_fn(&myClass::getNumber));
// just bind:
std::transform (vect.begin(), vect.end(), numVect.begin(), phx::bind(&myClass::getNumber, arg1));
// using more natural syntax
std::transform (vect.begin(), vect.end(), numVect.begin(), getNumber(arg1));
for(auto i : numVect)
std::cout << i << " ";
}
There is example of code which generates N objects of class A on the heap:
#include <vector>
#include <iostream>
#include <algorithm>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
using boost::make_shared;
using boost::shared_ptr;
class A
{
int val_;
public:
explicit A(int i) : val_(i) {}
int foo() const { return val_;}
};
template<typename T>
struct Generator
{
shared_ptr<T> operator()()
{
return make_shared<T>(std::rand() % 10 + 1);
}
};
int main()
{
std::vector< shared_ptr<A> > coll;
std::generate_n( back_inserter(coll), 3, Generator<A>());
std::vector<shared_ptr<A> >::const_iterator cit;
for (cit = coll.begin(); cit != coll.begin(); ++cit)
std::cout << (*cit)->foo() << std::endl;
return 0;
}
Code uses functor "Generator" and "generate_n" algorithm to do the job. I wounder about simplification of this task. boost:lambda, boost::phoenix are possible candidates (if they are?), and how to do it? Or maybe there are other alternatives?
Simple would be not to convolute the problem in the first case:
std::vector< std::shared_ptr<A> > ints;
for ( int i = 0; i < 3; ++i )
ints.push_back( std::make_shared<A>( std::rand()%10 + 1 ) );
Each different paradigm has its strengths and weaknesses, and in this case, in C++, trying to force a functional approach to the problem will make things more complex than they need be.
With lambda support in the compiler you could do:
std::vector< shared_ptr<A> > coll;
std::generate_n( back_inserter(coll), 3, [](){
return std::make_shared<A>(std::rand()%10 + 1); });
I have some (library API, so I can't change the function prototype) function which is written the following way:
void FreeContext(Context c);
Now, at some moment of my execution I have Context* local_context; variable and this is also not a subject to change.
I wish to use boost::bind with FreeContext function, but I need to retrieve Context from local variable Context*.
If I write my code the following way, the compiler says it's "illegal indirection":
boost::bind(::FreeContext, *_1);
I managed to solve this problem the following way:
template <typename T> T retranslate_parameter(T* t) {
return *t;
}
boost::bind(::FreeContext,
boost::bind(retranslate_parameter<Context>, _1));
But this solution doesn't seem really good to me. Any ideas on how to solve this using something like *_1. Maybe writing a small lambda function?
You could use Boost.Lambda which have overloaded the * operator for _n.
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <algorithm>
#include <cstdio>
typedef int Context;
void FreeContext(Context c) {
printf("%d\n", c);
}
int main() {
using boost::lambda::bind;
using boost::lambda::_1;
Context x = 5;
Context y = 6;
Context* p[] = {&x, &y};
std::for_each(p, p+2, bind(FreeContext, *_1));
return 0;
}
Use either Boost.Lambda or Boost.Phoenix to have a working operator* on a placeholder.
You can also place the Context pointer in a shared_ptr with a custom deleter:
#include <memory> // shared_ptr
typedef int Context;
void FreeContext(Context c)
{
printf("%d\n", c);
}
int main()
{
Context x = 5;
Context* local_context = &x;
std::shared_ptr<Context> context(local_context,
[](Context* c) { FreeContext(*c); });
}
Not sure this is relevant though. Good luck!
The following example from boost bind does not work for me:
#include <boost/bind.hpp>
struct A
{
int data;
};
int main()
{
A a;
boost::bind(&A::data, _1)(a) = 1;
}
error: assignment of read-only location 'boost::bind [with A1 = boost::arg<1>, M = int, T = A](&A::data, (<unnamed>::_1, boost::arg<1>())).boost::_bi::bind_t<R, F, L>::operator() [with A1 = A, R = const int&, F = boost::_mfi::dm<int, A>, L = boost::_bi::list1<boost::arg<1> >](((A&)(& a)))'
Am I doing anything wrong? The compiler is g++ 4.4.0
The result type of that bind expression is int (or rather const int&). I think you can override the return type:
boost::bind<int&>(&A::data, _1)(a) = 1;
UncleBens' solution is fine but I thought I'd add that if you use Boost.Lambda the problem disappears:
#include <boost/lambda/bind.hpp>
struct A {
int data;
};
int main() {
namespace bll = boost::lambda;
A a;
bll::bind(&A::data, bll::_1)(a) = 1;
}
And so it does if you use boost::mem_fn:
#include <boost/mem_fn.hpp>
struct A {
int data;
};
int main() {
boost::mem_fn(&A::data)(a) = 1;
}
I'm not sure what you want to do, but does Boost.Bind really overload the assignment operator? If you'd like to assign the value 1 to a.data using the returned function object I think you need to do something like this (also note that "a" needs to be bound by reference):
#include <boost/bind.hpp>
#include <boost/ref.hpp>
#include <cassert>
void foo()
{
A a;
boost::bind(&A::data, _1)(boost::ref(a), 1);
assert(a.data == 1);
}
If you need to use the assignment operator I think that using Boost.Lambda or Boost.Phoenix would be a better choice.