Using binder1st with custom functor - c++

I'd like to bind the first argument of my print functor to 0:
#include<iostream>
#include<functional>
using namespace std;
class Print : public std::binary_function<int,int,void>{
public:
void operator()(int val1, int val2)
{
cout << val1 + val2 << endl;
}
};
int main()
{
Print print;
binder1st(print,0) f; //this is line 16
f(3); //should print 3
}
The program above (based on an example from C++ Primer Plus) does not compile:
line16 : error : missing template arguments before ‘(’ token
What is wrong?
I don't want to use C++11 nor boost features.
Edited: operator() return type has been changed from bool to void for simplicity

As the error message says, you are missing template arguments before the (
This is what you want
std::binder1st<Print> f(print, 0);
However, you also need to make your operator() const as follows
bool operator()(int val1, int val2) const
Finally, this function needs to return something.

binder1st needs template-arguments, try
binder1st<Print> f(print, 0);
See the reference here.
Example
#include <iostream>
#include <functional>
#include <algorithm>
using namespace std;
int main () {
binder1st < equal_to<int> > equal_to_10 (equal_to<int>(),10);
int numbers[] = {10,20,30,40,50,10};
int cx;
cx = count_if (numbers,numbers+6,equal_to_10);
cout << "There are " << cx << " elements equal to 10.\n";
return 0;
}

std::binder1st is a class template, so it needs a template parameter.
binder1st<Print> f(print,0);
// ^^^^^^^
But if you really want to bind the second argument, then you need to use the aptly named std::binder2nd.

Related

Why is there an ambiguous call for templatized function?

I have a problem with creating a template in c++. I am using xcode for mac.
When passing an int to a swap function I get the error code "ambiguous call". However, passing strings works fine. Why is that?
This is my code
#include <iostream>
#include <cmath>
using namespace std;
template <typename T>
void swap(T& c, T& d)
{
T temp = c;
c = d;
d = temp;
}
int main()
{
int a = 10;
int b = 20;
swap(a, b); // this is an error "ambiguous call"
cout << a << "\t" << b;
string first_name = "Bob";
string last_name = "Hoskins";
swap(first_name, last_name); // this works
cout << first_name << "\t" << last_name;
return 0;
}
You have using namespace std; which brings std::swap into scope. This means the template swap that you have written conflicts with std::swap, and you get an ambiguous call when you pass it 2 ints.
Takeaway: Never do using namespace std;
The interesting part is that calling swap with 2 std::strings works. That's because there is a specialization of std::swap for std::string. The specialization is considered a better match, and so it's called instead of your own swap.

Expand variadic arguments in initializer list fails

I try to create a simple program in which I want to create vector of future arguments.
I created a wrapper function which is used to submit lambda functions and stores internally in a vector the future objects
I use an intermediate step in which I create an initiliazer_list using variadic arguments . But fails to compile. I try to use to call a function in order to push the elements in the vector and fails to compile as well
Below is the code
#include <iostream>
#include <thread>
#include <future>
#include <functional>
#include <cstdlib>
#include <chrono>
#include <initializer_list>
using namespace std;
using FunctPtr = function<int(int, int) >;
using FutureInt = future<int>;
using AsyncVector = vector<FutureInt>;
AsyncVector asyncVec;
template<typename... TemplatePtr>
void submit(TemplatePtr... pFunc)
{
auto initList {pFunc... };
for (auto & element : initList)
{
asyncVec.emplace_back(async(launch::async, element,4,5));
}
}
int main()
{
int a;
int b;
auto addPtr = [](int x, int y)->int
{
std::cout << "add :" << x + y << std::endl;
return x + y;
};
auto multPtr = [](int x, int y)->int
{
std::cout << "mult :" << x * y << std::endl;
return x * y;
};
// submit(add,4,5);
submit(addPtr, multPtr);
for (auto & v : asyncVec)
{
std::cout << "Wait for " << v.get() << std::endl;
}
}
Yes, they are of different types so cannot be in the same init-list easily.
Your best options should probably be:
Either push them all into asyncVec in the same fold-expression.
template<typename... TemplatePtr>
void submit(TemplatePtr... pFunc)
{
(asyncVec.emplace_back(async(launch::async, std::move(pFunc), 4, 5)), ...);
}
Or, if they all are of the same signature, type-erase them, like keeping them in an array of std::function.
template<typename... TemplatePtr>
void submit(TemplatePtr... pFunc)
{
for (auto &&element: {std::function<int(int, int)>(std::move(pFunc))...})
{
asyncVec.emplace_back(async(launch::async, std::move(element), 4, 5));
}
}
(I have specified function signature explicitly though compiler should be able to deduce it.)
Or, if all closures are captureless and of the same signature, simply cast them to the same type when calling submit:
using SameType = int (*)(int, int);
submit(static_cast<SameType>(addPtr), static_cast<SameType>(mulPtr));
This way your original submit should work as is.

C++ Function Pointer as Argument

I have tried multiple google searches and help guides, but I'm out of ideas on this one. I have a function pointer that I am using as an argument for another function. Both functions are within the same class. However, I keep getting type conversion errors. I'm sure this is just a syntax problem, but I can't understand what the correct syntax is. Here is a simplified version of my code:
Header File
#ifndef T_H
#define T_H
#include <iostream>
#include <complex>
namespace test
{
class T
{
public:
T();
double Sum(std::complex<double> (*arg1)(void), int from, int to);
int i;
std::complex<double> func();
void run();
};
}
#endif // T_H
Source File
#include "t.h"
using namespace test;
using namespace std;
//-----------------------------------------------------------------------
T::T()
{
}
//-----------------------------------------------------------------------
double T::Sum(complex<double>(*arg1)(void), int from, int to)
{
complex<double> out(0,0);
for (i = from; i <= to; i++)
{
out += arg1();
cout << "i = " << i << ", out = " << out.real() << endl;
}
return out.real();
}
//-----------------------------------------------------------------------
std::complex<double> T::func(){
complex<double> out(i,0);
return out;
}
//-----------------------------------------------------------------------
void T::run()
{
Sum(&test::T::func, 0, 10);
}
Whenever I try to compile, I get the following error:
no matching function for call to 'test::T::Sum(std::complex<double> (test::T::*)(),int,int)'
note: no known conversion for argument 1 from 'std::complex<double> (test::T::*)()' to 'std::complex<double>(*)()'
Any advice appreciated. Or at least a link to a thorough site on how to use function pointers. I am using Qt Creator 2.6.2, compiling with GCC.
Your Sum function expects pointer to a function. And then you try to call it with a pointer to a member function. Learn about pointers to members.
The code itself is a bit messy, I'll only correct the grammer to make it work.
firstly, you shall change the function prototype from
double Sum(std::complex<double> (*arg1)(void), int from, int to);
to
double Sum(std::complex<double> (T::*arg1)(void), int from, int to);
Meaning that it is a pointer to class T's member.
Then, when calling the function, you cant just arg1(),
for (i = from; i <= to; i++)
{
out += arg1();
cout << "i = " << i << ", out = " << out.real() << endl;
}
you have to use (this->*arg1)();
for (i = from; i <= to; i++)
{
out += (this->*arg1)();
cout << "i = " << i << ", out = " << out.real() << endl;
}
How to pass functions as arguments in C++? In general, use a template, unless you have very compelling reasons not do it.
template<typename Func>
void f(Func func) {
func(); // call
}
On the call side, you can now throw in a certain amount of objects (not just pointers to functions):
Functors;
struct MyFunc {
void operator()() const {
// do stuff
}
};
// use:
f(MyFunc());
Plain functions:
void foo() {}
// use
f(&foo) {}
Member functions:
struct X {
void foo() {}
};
// call foo on x
#include <functional>
X x;
func(std::bind(&X::foo, x));
Lambdas:
func([](){});
If you really want a compiled function and not a template, use std::function:
void ff(std::function<void(void)> func) {
func();
}

Using template in c++ - Returning values from method

I wanna a method that receives a generic type, and a generic type (that's defined in run time). In the example there's if I'm using a string type, It needs to return the first param lenght (in string); If I'm using a int type, needs to return the biggest (int integer).
Have a look:
#include "stdafx.h"
#include <sstream>
#include <iostream>
#include <conio.h>
#include <sstream>
#include <string>
#include <atldbcli.h>
#import "C:\Program Files\Common Files\System\ADO\msado15.dll" \
no_namespace rename("EOF", "EndOfFile")
using namespace std;
class Test
{
public:
template<class T>
T returnVal(T valueOne, T valueTwo);
};
template<class T>
T Test::returnVal(T valueOne, T valueTwo)
{
if(typeid(valueOne) == typeid(string))
{
string teste = valueOne;
int testeInt = teste.size();
ostringstream testeString;
testeString << testeInt;
teste = testeString.str();
return teste;
}
else
return valueOne > valueTwo? valueOne:valueTwo;
}
int main()
{
string reference = "stringVal";
Test ref;
cout << ref.returnVal<string>(reference, "asasas") << endl;
cout << ref.returnVal<int>(10, 485);
getch();
return 0;
}
However, when the main function calls ref.returnVal(10, 485); it's show a message error: 'return' : cannot convert from 'std::string' to 'int'
Does anybody know what's wrong?
Thanks
this is not the proper way to do what you want. You can't use typeid to switch between types and do different operations, because all the different paths still have to be compiled, and inside your if you do return a string while your method returns an int.
google template specialization, that's what you need I guess...
#include <string>
template <class T>
int returnVal(T valueOne, T valueTwo);
template <>
int returnVal<std::string>(std::string valueOne, std::string valueTwo)
{
return (int)valueOne.length();
}
template <>
int returnVal<int>(int valueOne, int valueTwo)
{
return std::max(valueOne, valueTwo);
}
int main()
{
int x = returnVal(std::string("Hello"), std::string("World!"));
int y = returnVal(1,2);
return 0;
}
Unless I'm misunderstanding you, you could achieve this with template specialization?
All previous answers clearly identify the problem. As for a better way to do it:
class Test
{
public:
string returnVal(string valueOne, string valueTwo)
{
string teste = valueOne;
int testeInt = teste.size();
ostringstream testeString;
testeString << testeInt;
teste = testeString.str();
return teste;
}
int returnVal(int valueOne, int valueTwo)
{
return valueOne > valueTwo? valueOne:valueTwo;
}
};
If you instantiate your template for type int, it looks like this:
int Test::returnVal(int valueOne, int valueTwo)
{
if(typeid(valueOne) == typeid(string)) // This will be false
{
string teste = valueOne;
int testeInt = teste.size();
ostringstream testeString;
testeString << testeInt;
teste = testeString.str();
return teste;
}
else
return valueOne > valueTwo? valueOne:valueTwo;
}
The problem is that the then-clause of your if returns a string even though the return type of the function is int. The fact that the then-clause will never execute because typeif(valueOne) can't possible be string doesn't matter because the type checker does not care about that. All he sees is a return statement that returns a string, so that's an error.
To do what you want, you should simply overload your function for strings and remove all the string-specific code from the templated function.

mem_fun_ref question

Why is this code resulting in a compiler error?
#include <iostream>
#include <algorithm>
using namespace std;
class X
{
public:
void Print(int x)
{
cout << x << endl;
}
};
int main()
{
X x;
mem_fun_ref<void, X, int>(&X::Print) p;
};
Error
main.cpp:18: error: expected ; before p
mem_fun_ref is a function template, so it does not name a type.
mem_fun_ref<void, X, int>(&X::Print) is a function call that returns a value, so it makes no sense that there is a p following it.
The return value of that function call is a mem_fun1_ref_t<void, X, int>, in case you were looking for that.
Did you intend to write
mem_fun1_ref_t<void, X, int> p(&X::Print);
^^^^ ^^^
instead? mem_fun_ref is not a class template, but a function template.