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 << " ";
}
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 need to copy the contents of a std::list into an array, wherein the array is struct of array. Below is the code implementation of it.
#include <iostream>
#include <string>
using namespace std;
typedef struct
{
int height;
int width;
int length;
}dimensions;
GetDimensions(list<std::string>, *int); // Function that copies the content of list to array passed as second parameter
int main()
{
dimensions cuboid[10];
int plane[10];
list<std::string> planeList = GetList();//Function that returns list of elements
list<std::string> dimensionList = GetList();
GetDimensions(planeList,&plane);//This is fine, as it is a simple array
GetDimensions(dimensionList,&cuboid.height);//Trouble in implementation of this usecase, for cuboid.height, cuboid.width and cuboid.height.
return 0;
}
GetDimensions(list<std::string>dimensionList, int* dimensionParams)
{
int i=0;
for(list<std::string>::iterator it = dimensionList.begin(); it != dimensionList.end(); ++it)
{
dimensionParams[i] = stoi(*it);
i++;
}
}
Here, I need GetDimensions() function to copy the list (passed as first parameter) to array (second parameter). The implemented function works well for simple array plane. But how to pass the array of struct as parameter to the function ?
I will be getting the std::list as cuboid.height, cuboid.width and cuboid.length. So the function has to copy the contents of list from cuboid[0].height to cuboid[i].height respectively. Is there any specific function to copy the content directly?
Use std::array 's instead. Then your problem can be reduced to passing two different types of arrays to a single function.
This can be solved
either by good old function overloads
or in c++17 function template with
if-constexpr.
Following is an example code with templated function with if-constexpr (See live online)
#include <iostream>
#include <string>
#include <list>
#include <array>
#include <type_traits> // std::is_same_v
struct dimensions // no need to typedef here
{
int height;
int width;
int length;
};
template<typename T>
void GetDimensions(const list<std::string>& dimensionList, T& dimensionParams)
^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //---> pass list by const-ref as the values are non-modifying
{
int i{0};
if constexpr (std::is_same_v<std::array<int, 10>, T>)
{
for(const std::string& str: dimensionList) dimensionParams[i++] = std::stoi(str);
}
else
{
for(const std::string& str: dimensionList) dimensionParams[i++].height = std::stoi(str);
}
}
int main()
{
std::array<dimensions, 10> cuboid; // use std::array instead of VLA
std::array<int, 10> plane;
std::list<std::string> planeList{"1", "2"}; // some list
std::list<std::string> dimensionList{"1", "2"};
GetDimensions(planeList, plane);
GetDimensions(dimensionList, cuboid);
return 0;
}
Also note that:
You have not specified the return type of GetDimensions function.
You probably want to return void there.
in C++ you do not need to use typedef alias for struct { ... }.
last but not least, do not practice with using namespace std;
You can do this with boost::transform_iterator.
#include <iostream>
#include <string>
#include <algorithm>
#include <functional>
#include <boost/iterator/transform_iterator.hpp>
struct dimensions {
int height;
int width;
int length;
};
template <typename OutputIt>
void GetDimensions(std::list<std::string> dimensionList, OutputIt dimensionParams)
{
// N.b. taking the address of a standard library function is undefined, so wrap in a lambda
auto stoi = [](std::string s){ return std::stoi(s); };
std::copy(boost::make_transform_iterator(dimensionList.begin(), stoi),
boost::make_transform_iterator(dimensionList.end(), stoi),
dimensionParams);
}
int main() {
dimensions cuboid[10];
int plane[10];
std::list<std::string> planeList = GetList();
std::list<std::string> heightList = GetList();
std::list<std::string> widthList = GetList();
std::list<std::string> lengthList = GetList();
GetDimensions(planeList, plane);
GetDimensions(heightList,
boost::make_transform_iterator(cuboid, std::mem_fn(&dimensions::height)));
GetDimensions(widthList,
boost::make_transform_iterator(cuboid, std::mem_fn(&dimensions::width)));
GetDimensions(lengthList,
boost::make_transform_iterator(cuboid, std::mem_fn(&dimensions::length)));
return 0;
}
Is it possible to construct a std::pair if I want to construct the embedded std::string with a constructor that takes more than 1 argument?
E.g., this is legal:
#include <iostream>
#include <utility>
#include <string>
int main()
{
std::pair<int, int> pair(2, 3);
return 0;
}
...and this is legal:
#include <iostream>
#include <utility>
#include <string>
int main()
{
std::pair<int, std::string> pair(2, "hello");
return 0;
}
...but I wonder if something like the following is possible:
#include <iostream>
#include <utility>
#include <string>
int main()
{
std::pair<int, std::string> pair{2, {"hello", 3}}; //Unclear if some variation/combination of parentheses and curly braces can make this legal.
return 0;
}
I think the above is correct syntax to use "uniform initializer lists", but this won't work for my purposes because I'm using a pre-C++11 compiler. Is there some way to pull this off with pre-C++11 syntax?
To clarify, I'm trying to use this std::string constructor:
basic_string( const CharT* s,
size_type count,
const Allocator& alloc = Allocator() );
As context on why I'm asking this, this is for academic curiosity (correct me if wrong): I think doing one-line construction like this is more efficient because the std::pair and its members are simply created and initialized all in one go. Whereas if I did something like this (using C++11 syntax)...
#include <iostream>
#include <utility>
#include <string>
int main()
{
std::pair<int, int> pair(2, 3);
std::pair<int, std::string> pair2 = {2, {"hello", 3}};
return 0;
}
...then I'm technically creating a std::pair<int, std::string> whose members are default-contructed, followed by invoking std::pair's operator=, followed by invoking the operator= on the pair's members.
Just write:
std::pair<int, std::string> pair( 2, std::string( "hello", 3 ) );
As for this declaration:
std::pair<int, std::string> pair2 = {2, {"hello", 3}};
then in fact it is equivalent to this declaration:
std::pair<int, std::string> pair{2, { "hello", 3}};
due to the copy constructor elision. Take into account that there is neither assignment operator because it is a declaration.
Consider the following example:
#include <iostream>
#include <string>
int main()
{
struct Pair
{
std::string s;
int i;
Pair(int i, const std::string &s) : i(i), s(s)
{
std::cout << "Pair( int, std::string )" << std::endl;
}
Pair( const Pair &p) : i(p.i), s(p.s)
{
std::cout << "Pair( const Pair & )" << std::endl;
}
};
Pair p1{ 2, { "hello", 3 } };
Pair p2 = { 2, { "hello", 3 } };
}
The program output is:
Pair( int, std::string )
Pair( int, std::string )
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;
}
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); });