C++: std::bind -> std::function - c++11

I have several functions which receive the following type:
function<double(int,int,array2D<vector<double *>>*)>
Where array2D is a custom type. Further, I have a function which takes the following as arguments:
double ising_step_distribution(double temp,int i,int j,array2D<vector<double *>>* model)
Right now, in order to bind the first value, temp, and return a functor which has the correct signature, I am writing:
double temp = some_value;
function<double(int,int,array2D<vector<double *>>*)> step_func =
[temp](int i, int j, array2D<vector<double *>>* model){
return ising_step_distribution(temp,i,j,model);
}
}
And this works. However, the following breaks:
auto step_func =
[temp](int i, int j, array2D<vector<double *>>* model){
return ising_step_distribution(temp,i,j,model);
}
}
With the following error:
candidate template ignored:
could not match
'function<double (int, int, array2D<vector<type-parameter-0-0 *, allocator<type-parameter-0-0 *> > > *)>'
against
'(lambda at /Users/cdonlan/home/mcmc/main.cpp:200:25)'
void mix_2D_model(function<double(int,int,array2D<vector<T*>>*)> step_distribution_func,...
And so, the code clump is ugly, obfuscative and repetitive (because I am making many of these).
I have been reading the documentation, and I understand that I should be able to write:
function<double(int,int,array2D<vector<double *>>*)> step_func =
bind(ising_step_distribution,temp,_1,_2,_3);
However, the only examples I have seen are for functions of type function<void()>. This one fails with an error:
// cannot cast a bind of type
// double(&)(double,int,int,array2D<vector<double *>>*)
// as function<double(int,int,...)
How do I get a visually clean bind and cast?

How do I get a visually clean bind and cast?
One way is:
using F = function<double(int,int,array2D<vector<double *>>*)>;
auto step_func =
[temp](int i, int j, array2D<vector<double *>>* model){
return ising_step_distribution(temp,i,j,model);
}
}
And then:
auto step_func_2 = F(step_func);
mix_2D_model(step_func_2, ...);
Or:
mix_2D_model(F(step_func), ...);

Related

Can functions return user-defined types in Processing?

I wrote a class to represent complex numbers in Processing (which I call Complex). I want to implement basic arithmetic functions on complex numbers. However, if I declare the return type of a method to be Complex and try to return a new object, I get an error which says that says
"Void methods cannot return a value". I also get errors for the parentheses after the function name, as well as the comma separating the x and y parameters.
However, I have noticed that if I change the return type to something built-in (such as int or String) and return some arbitrary value of the correct type, all of these errors disappear. I have also not seen anay examples of functions returning non-built-in types either. These two facts lead me to believe that I may not be able to return object of a class I defined. So my question is whether it is possible to return an object from a class I have defined in Processing. If not, is there any way around this?
Here is my code:
class Complex {
int re, im; // real and imaginary components
Complex(int re, int im) {
this.re = re;
this.im = im;
}
}
Complex add(Complex x, Complex y) {
int re_new = x.re + y.re;
int im_new = x.im + y.im;
return new Complex(re_new, im_new);
}
With Processing just as with java you can return any object type with a function. Here's a short proof of concept for you to copy, paste and try:
void setup() {
Complex a = new Complex(1, 5);
Complex b = new Complex(2, 6);
Complex c = add(a, b);
println("[" + c.re + ", " + c.im + "]");
}
void draw() {
}
class Complex {
int re, im; // real and imaginary components
Complex(int re, int im) {
this.re = re;
this.im = im;
}
}
Complex add(Complex x, Complex y) {
int re_new = x.re + y.re;
int im_new = x.im + y.im;
return new Complex(re_new, im_new);
}
I noticed that the add method light up as if it was shadowing another method, but it didn't prevent it to run as intended.
If the situation persists, you may want to post more code, as the problem may be somewhere unexpected. Good luck!

Sorting a structure vector by a value within the struct

First of all, I would like to thank you for the assistance. I am attempting to sort a vector of structs by a value within the struct, which in this case is an double. The struct looks like this.
struct countryInfoStruct
{
int countryNumber;
double latitude;
double longitude;
string city;
string country;
double distance;
};
My vector name is:
vector<countryInfoStruct> countries;
Which is populated by a .csv file, which works correctly. My problem is sorting. I created a function that is intended to sort the vector; however, something is missing. The error that I am getting is
CountryData::countryInfoStruct incomplete type is not allowed
I have researched this many times, but have not been able to fix it. The error message is underlining "countryInfoStruct". Below is my sortVector Function.
void CountryData::sortVector()
{
CountryData m;
auto sortFunc = [](countryInfoStruct a, countryInfoStruct b) -> bool {
return a.distance < b.distance;
}
Of note: I know that I am missing the iterator below, but this is because I have not been able to get the actual function to work.
sort(countries.begin(), countries.end(), sortVector);

using a union-like class in an std::initializer_list

In the code below I show union-like class S which contains two non-related structs B and C. I show how to instantiate the non-POD std::string and delete it again and then switch S to S::CC and set the num int.
#include <vector>
#include <string>
#include <iostream>
#include <memory>
struct B
{
B() {}
~B() {}
std::string str;
void Func1() {}
};
struct C
{
C() {}
~C() {}
int num;
void Func2() {}
};
struct S
{
S() { tag = CC; }
S( const S& s )
{
switch( s.tag )
{
case BB:
new ( &b.str ) std::string;
b.str = s.b.str;
break;
case CC:
c.num = s.c.num;
default:
break;
}
}
~S()
{
switch( tag )
{
case BB:
b.str.~basic_string< char >();
break;
case CC:
c.num = 0;
break;
default:
break;
}
}
enum { BB, CC } tag;
union
{
B b;
C c;
};
};
struct H
{
H( std::initializer_list< S > initializerList ) : initListVect( initializerList ) {}
std::vector< S > initListVect;
};
int main()
{
S s;
s.tag = S::BB;
new ( &s.b.str ) std::string; // docs say use new placement to create memory
s.b.str = "bbb";
s.b.str.~basic_string< char >(); // string usage in B ok
s.tag = S::CC;
s.c.num = 333; // int usage in C ok
H h { }; // what should the init list be if I wanted 3 list elements S::BB, S::CC, S::BB?
return 0;
}
My goal, however, is to use S in an std::initializer_list. I don’t know what the format should be for initializeing h. What should the arguments be if I wanted to initialize h with these S::BB, S::CC, S::BB?
My compiler is VS2015.
Edit:
This post’s history: my posting comes from a need for a definitive answer to the question of storing compile-time-deduceable heterogeneous objects in an std::initializer_list. This question has been asked many times before and there have been many attempts at answers (see Heterogeneous containers in C++). The most simplistic answer is to use polymorphism, but this ignores the power of being able to define a type at compile time (templates). Besides, heterogeneous, non-related objects grouped together polymorphically means a lot of derived data members are useless, which sows usage and maintenance confusion downstream. Other advice given was to use boost::any or boost::variant, but this has the same weakness as polymorphism and reduces message declaration clarity. Another attempt at container object heterogeneity was the use of std::tuple, but although an initializer_list can certainly contain tuples, this approach too ignores compile-time type resolution. I even found a paper written in 1999 called Heterogeneous, Nested STL Containers in C++ which uses template template arguments to solve the heterogeneity problem. After all this, I settled on class-like unions which led to my posting here. Class-like unions for non-related/heterogeneous container objects has perfect message declaration clarity, no object size ambiguity, and is compile time template-able, and it leads to excellent downstream maintenance scenarios.
Edit2: (5 weeks later) Here is what has happened. 1) I implemented a full class-like union solution given the advice in this posting. The result was tedious and unwieldy with ‘tag’ being used to identify which sub-method to call for each new functionality. Low grade regarding code maintenance. 2) c++17 has accepted std::variant. Since that is currently not yet implemented in VS2015 Update 2, I set about using boost::variant. See What is the right c++ variant syntax for calling a member function set to a particular variant? which uses the Visitor pattern to allow access to initialized variant members and member functions. This eliminates the ‘tag’ switches and variant ‘get’ calls. Bottom line: I dropped my class-like union and adopted variant for creating maintainable code that uses initializer_list to store variant member functionality all being initializable at compile time (read: highly maintainable).
Alright, I'm feeling generous and I've made custom unions myself so he're some stuff that'll get you set up. I've rewritten your S structure to be more compliant and usable. (I've made changes marked by comments)
struct S
{
S() : tag(CC) // initializer
{
new (&c) C; // make C object
}
S(int num) : tag(CC) // added integer constructor
{
new (&c) C;
c.num = num;
}
S(const std::string& str) : tag(BB) // added string constructor
{
new (&b) B;
b.str = str;
}
S( const S& s ) : tag(s.tag)
{
if (tag == CC)
{
new (&c) C; // construct c
c.num = s.c.num;
}
else if (tag == BB)
{
new (&b) B; // construct b, not b.str
b.str = s.b.str;
}
}
S& operator= (const S& s) // added assignment operator
{
if (tag == s.tag) // just copy b or c
{
if (tag == CC)
c = s.c;
else
b = s.b;
}
else // reconstruct b or c
{
if (tag == CC)
{
c.~C(); // destroy c
new (&b) B; // construct b
b.str = s.b.str;
}
else
{
b.~B(); // destroy b
new (&c) C; // construct c
c.num = s.c.num;
}
tag = s.tag;
}
return *this;
}
~S()
{
if (tag == CC)
{
c.~C(); // destroy c
}
else if (tag == BB)
{
b.~B(); // destroy b, not b.str
}
}
enum { BB, CC } tag;
union
{
B b;
C c;
};
};
One of the things that you were doing improperly was skipping the construction and destruction of B and C and going straight for the internal variables. You should always create and destroy types properly even when they may be trivial. While this may work out, not initializing these objects properly is only asking for trouble (It also makes it easier should you change B or C in the future).
To make using the class easier, I added in the proper constructors for std::string and int as well as an assignment operator. Because now that we can construct the objects how we want, your main() could look like this:
int main()
{
S s; // default S
s = std::string("bbb"); // set to string
s = 333; // set to number
// use initialization list
H h { std::string("bb"), 33, std::string("bb") };
return 0;
}
I encourage you to modify B and C to use constructors to build their internals rather than relying on S.

Trying to use lambda functions as predicate for condition_variable wait method

I am trying to make the producer-consumer method using c++11 concurrency. The wait method for the condition_variable class has a predicate as second argument, so I thought of using a lambda function:
struct LimitedBuffer {
int* buffer, size, front, back, count;
std::mutex lock;
std::condition_variable not_full;
std::condition_variable not_empty;
LimitedBuffer(int size) : size(size), front(0), back(0), count(0) {
buffer = new int[size];
}
~LimitedBuffer() {
delete[] buffer;
}
void add(int data) {
std::unique_lock<std::mutex> l(lock);
not_full.wait(l, [&count, &size]() {
return count != size;
});
buffer[back] = data;
back = (back+1)%size;
++count;
not_empty.notify_one();
}
int extract() {
std::unique_lock<std::mutex> l(lock);
not_empty.wait(l, [&count]() {
return count != 0;
});
int result = buffer[front];
front = (front+1)%size;
--count;
not_full.notify_one();
return result;
}
};
But I am getting this error:
[Error] capture of non-variable 'LimitedBuffer::count'
I don't really know much about c++11 and lambda functions so I found out that class members can't be captured by value. By value though, I am capturing them by reference, but it seems like it's the same thing.
In a display of brilliance I stored the struct members values in local variables and used them in the lambda function, and it worked! ... or not:
int ct = count, sz = size;
not_full.wait(l, [&ct, &sz]() {
return ct != sz;
});
Obviously I was destroying the whole point of the wait function by using local variables since the value is assigned once and the fun part is checking the member variables which may, should and will change. Silly me.
So, what are my choices? Is there any way I can make the wait method do what it has to do, using the member variables? Or I am forced to not use lambda functions so I'd have to declare auxiliary functions to do the work?
I don't really get why I can't use members variables in lambda functions, but since the masters of the universe dessigned lamba functions for c++11 this way, there must be some good reason.
count is a member variable. Member variables can not be captured directly. Instead, you can capture this to achieve the same effect:
not_full.wait(l, [this] { return count != size; });

Strange error when sorting strings with D

I am in the process of learning D (I decided it would be a better beginner friendly language than C++) and I decided to give myself the excercise of implementing a general quicksort in D. My program runs fine when sorting integers but it doesn't compile and throws a strange error when sorting strings.
Here is my code:
import std.stdio, std.algorithm;
T[] quickSort(T)(T[] input) {
if (input.length <= 1) {return input;}
ulong i = input.length/2;
auto pivot = input[i];
input = input.remove(i);
T[] lesser = [];
T[] greater = [];
foreach (x; input) {
if (x<=pivot)
{
lesser ~= x;
}
else
{
greater ~=x;
}
}
return (quickSort(lesser) ~ cast(T)pivot ~ quickSort(greater));
}
void main() {
//Sort integers, this works fine
//writeln(quickSort([1,4,3,2,5]));
//Sort string, throws weird error
writeln(quickSort("oidfaosnuidafpsbufiadsb"));
}
When I run it on a string it throws this error:
/usr/share/dmd/src/phobos/std/algorithm.d(7397): Error: template std.algorithm.move does not match any function template declaration. Candidates are:
/usr/share/dmd/src/phobos/std/algorithm.d(1537): std.algorithm.move(T)(ref T source, ref T target)
/usr/share/dmd/src/phobos/std/algorithm.d(1630): std.algorithm.move(T)(ref T source)
/usr/share/dmd/src/phobos/std/algorithm.d(1537): Error: template std.algorithm.move cannot deduce template function from argument types !()(dchar, dchar)
/usr/share/dmd/src/phobos/std/algorithm.d(7405): Error: template std.algorithm.moveAll does not match any function template declaration. Candidates are:
/usr/share/dmd/src/phobos/std/algorithm.d(1786): std.algorithm.moveAll(Range1, Range2)(Range1 src, Range2 tgt) if (isInputRange!(Range1) && isInputRange!(Range2) && is(typeof(move(src.front, tgt.front))))
/usr/share/dmd/src/phobos/std/algorithm.d(7405): Error: template std.algorithm.moveAll(Range1, Range2)(Range1 src, Range2 tgt) if (isInputRange!(Range1) && isInputRange!(Range2) && is(typeof(move(src.front, tgt.front)))) cannot deduce template function from argument types !()(string, string)
helloworld.d(9): Error: template instance std.algorithm.remove!(cast(SwapStrategy)2, string, ulong) error instantiating
helloworld.d(31): instantiated from here: quickSort!(immutable(char))
helloworld.d(31): Error: template instance helloworld.quickSort!(immutable(char)) error instantiating
the problem is that strings are immutable so remove won't work (as it manipulates the string)
you can fix that by not removing and not inserting the pivot in the concat:
auto pivot = input[i];
//input = input.remove(i); //<- remove this line
T[] lesser = [];
//...
return (quickSort(lesser) ~ quickSort(greater)); //<- remove cast(T)pivot ~
or by passing in a dup:
writeln(quickSort("oidfaosnuidafpsbufiadsb".dup));
You have to put a "d" behind the string to make it utf-32, otherwise remove won't accept it.
writeln(quickSort("oidfaosnuidafpsbufiadsb"d.dup));

Resources