I am quite new to C++ and I am experiencing some of its features. In particular, I would like to implement a generic Divide and Conquer procedure that takes as parameter the 'functional code' to solve the problem. Actually what I have in mind is that 'Divide and Conquer' is a higher order function taking as parameters:
- a function
basecase()
to test whether the we reached the base case - a function
solvecase()
to solve the base case - a function
divide()
to split the problem in two subproblems - a function
conquer()
that takes to partial solutions and builds one solution out of the two.
To do this, I used templates: in particular, type A
is the type of the input problem, type B
is the type of the output problem and type C
will probably be a boolean (the result type of the test for base case).
There is also other stuff, like the use of async()
to compute concurrently the solution, but this is not the focus of my question.
My question is: why do I get the following message when I compile, complaining about conflicting types ?
D&C.cpp: In function ‘int main(int, char**)’:
D&C.cpp:67:92: error: no matching function for call to ‘divideAndConquer(std::string&, main(int, char**)::__lambda4&, main(int, char**)::__lambda5&, main(int, char**)::__lambda6&, main(int, char**)::__lambda7&)’
divideAndConquer(text, lambda_basecase, lambda_divide, lambda_conquer, lambda_solvecase);
^
D&C.cpp:67:92: note: candidate is:
D&C.cpp:10:3: note: template<class A, class B, class C> B divideAndConquer(A, C, A, B, B)
B divideAndConquer(const A x, C basecase, A divide, B conquer, B solvecase)
^
D&C.cpp:10:3: note: template argument deduction/substitution failed:
D&C.cpp:67:92: note: deduced conflicting types for parameter ‘A’ (‘std::basic_string<char>’ and ‘main(int, char**)::__lambda5’)
divideAndConquer(text, lambda_basecase, lambda_divide, lambda_conquer, lambda_solvecase);
The Code is the following: basically the idea is to use the Divide and Conquer procedure to look for the instances of a target string into a text, but to be general enough to reuse this schema to solve also other problems (e.g. the Fibonacci numbers).
#include <iostream>
#include <thread>
#include <string>
#include <fstream>
#include <future>
using namespace std;
template <typename A, typename B, typename C>
B divideAndConquer(const A x, C basecase, A divide, B conquer, B solvecase)
{
if (basecase(x))
return solvecase(x);
A probl1 = divide(x,1);
A probl2 = divide(x, 2);
auto sol1f = async(divideAndConquer, probl1, basecase, divide, conquer, solvecase);
B sol2 = divideAndConquer(probl2, basecase, divide, conquer, solvecase);
B sol1 = sol1f.get();
return (conquer(sol1, sol2));
}
int splitOnWhitespaces(const string& text, int half, string direction){
int i=half, N = text.length();
if (direction.compare("forward")==0){
while(text[i]!=' ' && text[i] != '\n' && i < N)
i++;
}
else{
while(text[i]!=' ' && text[i] != '\n' && i >= 0)
i--;
if (i<=0 || i==N)
return -1;
else
return i;
}
}
int main(int argc, char *argv[]){
string text= "Nel mezzo del cammin di nostra vita mi ritrovai per una selva oscura, che la diritta via era smarrita.";
string target = "nel";
int base = 10;
auto lambda_basecase = [base](string text){return text.length()<=base;};
auto lambda_divide= [](string text, int subprobl){
int half = text.length()/2;
half = splitOnWhitespaces(text, half, "forward");
if (half==-1)
half = splitOnWhitespaces(text, half, "backward");
if (half==-1)
throw runtime_error("Error splitting the string: no whitespaces\n");
return ((subprobl==1) ? string(text, 0, half) : string(text, half));
};
auto lambda_conquer = [](int count1, int count2){return count1+count2;};
auto lambda_solvecase = [target](string baseText){
int found = 0;
int start = 0;
int len = target.length();
while(baseText.find(target, start)!=string::npos ){
found++;
int position = baseText.find(target, start);
start = position + len + 1;
}
return found;
};
divideAndConquer(text, lambda_basecase, lambda_divide, lambda_conquer, lambda_solvecase);
return 0;
}
I am studying template programming right now, so any help about this issue and any reference to (good) books or webpages explaining the matter would be appreciated. Thank you in advance!