Consider the follow code:
Unit& accessTree(std::string unitId2Find, BSTree<Unit> &tree)
{
Unit searchU;
searchU.SetId(unitId2Find);
return tree.search(searchU);
}
int main()
{
using namespace std::placeholders;
BSTree<Unit> tesTree;
auto getUnit = std::bind(accessTree, _1, std::cref(tesTree));'
Registration R;
..... //Setting required data
int i = R.GetCredits(getUnit); //Causes the error.
Now I've tried two different types of implementation:
1
template<typename Fn>
unsigned Registration::GetCredits(Fn access)
{
unsigned sum = 0;
for(unsigned i = 0; i < GetSize(); i++)
sum += results[i].GetCredits(access(results[i].GetUnit()));
return sum;
}
template<typename Fn>
float Registration::CalculateGPA(Fn access)
{
float total = 0;
for (int i = 0; i < results.getLength(); i++)
{
total = total + results[i].GetGPAvalue() * results[i].GetCredits(access(results[i].GetUnit()));
}
return total / GetCredits(access);
}
2
unsigned Registration::GetCredits(Unit& (*access) (std::string & uId))
{
unsigned sum = 0;
for(unsigned i = 0; i < GetSize(); i++)
sum += results[i].GetCredits(*access(results[i].GetUnit()));
return sum;
}
float Registration::CalculateGPA(Unit& (*access) (std::string & uId))
{
float total = 0;
for (int i = 0; i < results.getLength(); i++)
{
total = total + results[i].GetGPAvalue() * results[i].GetCredits(*access(results[i].GetUnit()));
}
return total / GetCredits(func);
}
Compiler:
||=== Build: Debug in TesterProgram (compiler: GNU GCC Compiler) ===|
E:\CODE\DSA\TesterProgram\BSTree.h||In member function 'elemType& BSTree::search(const elemType&) const [with elemType = Unit]':|
E:\CODE\DSA\TesterProgram\BSTree.h|189|warning: control reaches end of non-void function [-Wreturn-type]|
E:\CODE\DSA\TesterProgram\src\Regist.cpp||In member function 'Vector& Registration::GetHighestResults()':|
E:\CODE\DSA\TesterProgram\src\Regist.cpp|100|warning: reference to local variable 'vec' returned [-Wreturn-local-addr]|
E:\CODE\DSA\TesterProgram\src\Regist.cpp||In member function 'Vector& Registration::GetLowestResults()':|
E:\CODE\DSA\TesterProgram\src\Regist.cpp|125|warning: reference to local variable 'vec' returned [-Wreturn-local-addr]|
..\TesterProgram\vector.h||In member function 'const T& Vector::operator[](unsigned int) const [with T = Result]':|
..\TesterProgram\vector.h|277|warning: control reaches end of non-void function [-Wreturn-type]|
obj\Debug\main.o||In function main':|
E:\CODE\DSA\TesterProgram\main.cpp|81|undefined reference tounsigned int Registration::GetCredits(std::_Placeholder<1>, std::reference_wrapper const>))(std::string, BSTree&)> >(std::_Bind(std::_Placeholder<1>, std::reference_wrapper const>))(std::string, BSTree&)>)'|
||=== Build failed: 1 error(s), 4 warning(s) (0 minute(s), 0 second(s)) ===|
What is going on here, I've had a look at related stuff on this site but nothing seems to directly answer this question.
I don't know how to use boost:: Is this something that is required, how would it be used?
Or is this a run time/ compiler issue? Is it not define in the compilation process when it needs to be? Is there a work around?
Thanks SO
Working on MVCE now.. update soon
Related
Suppose I have the following code
#include <stdio.h>
#include <stdlib.h>
int foo(int bar[3][3]){
return bar[1][1];
}
int main(){
int* bar = (int*) malloc(9 * sizeof(int));
for(int i = 0; i < 9; i++){
bar[i] = i;
}
int test = foo(bar);
printf("%d\n", test);
}
Compiling this with C gives a warning
warning: incompatible pointer types passing 'int *' to parameter of type 'int (*)[3]' [-Wincompatible-pointer-types]
int test = foo(bar);
But still outputs the expected result of 4 (Although I imagine the warning is a sign of UB)
Compiling with g++ gives an error
error: no matching function for call to 'foo'
int test = foo(bar);
note: candidate function not viable: no known conversion from 'int *' to 'int (*)[3]' for 1st argument
int foo(int bar[3][3]){
I cannot change the function signature of bar but would like to just pass in a simple pointer to the array. What is the simplest typecast/change of code that would make this compile with no UB with g++. This is for code that I am generating with a Python script while looking at the function signature of bar so the simpler the solution the better. (This is just an example)
Quick and dirty fix:
foo(reinterpret_cast<int(*)[3]>(bar)); // C++ only
foo((int(*)[3])bar); // C and C++
Replaces the implicit cast present in C language with an explicit one to let the C++ compiler know you are intending to circumvent the type-system.
Without dynamic memory allocation:
int main(void) {
int bar[3][3];
for (int i=0; i<9; ++i) {
bar[i / 3][i % 3] = i;
}
printf("%d\n", foo(bar));
}
With: (C)
int main(void) {
int (*bar)[3] = malloc(3 * sizeof(int[3]));
for (int i=0; i<9; ++i) {
bar[i / 3][i % 3] = i;
}
printf("%d\n", foo(bar));
}
What is the simplest typecast/change of code that would make this compile with no UB with g++
int main(){
int bar[3][3];
for(int i = 0; i < 9; i++){
bar[i / 3][i % 3] = i;
}
int test = foo(bar);
printf("%d\n", test);
}
Works in both C++ and C
First of all, I don't want to use sort. This is just an illustration example. The main purpose of this question is that I want to:
find all possible combinations of m numbers out of n numbers and
process them, then return the unique processed result (since the
processed results of all possible combinations will be compared).
Question start at here
The following code get all possible combinations M numbers out of N numbers. Sum the M numbers and find the largest sum. In doing this I used a recursion function.
However, it seems that I must define a global variable to store the temporary largest sum. Is there any way to get rid of this global variable? For example, define the recursion function to return the largest sum... I don't want the global variable just become an argument &max_sum in the find_sum, since find_sum already have too many arguments.
#include <iostream>
#include <vector>
void find_sum(const std::vector<int>& ar, std::vector<int>& combine,
int index, int start);
int max_sum =0;
int main() {
int N = 10;
int M = 3;
std::vector<int> ar(N);
ar = {0,9,2,3,7,6,1,4,5,8};
int index = 0, start =0;
std::vector<int> combine(M);
find_sum(ar, combine, index, start);
std::cout << max_sum <<std::endl;
return 0;
}
void find_sum(const std::vector<int>& ar, std::vector<int>& combine,
int index, int start) {
if(index == combine.size()) {
int sum =0;
for(int i=0; i<index; ++i) {
sum += combine[i];
}
if(max_sum < sum) {
max_sum = sum;
}
return ;
}
for(int i = start;
i < ar.size() && ar.size()-i > combine.size()-index;
++i) {
combine[index] = ar[i];
find_sum(ar, combine, index+1, start+1);
}
}
An approach that scales well is to turn find_sum into a function object. The trick is to define a struct with an overloaded () operator that takes a certain set of parameters:
struct FindSum
{
void operator()(const std::vector<int>& ar, std::vector<int>& combine,
int index, int start){
/*ToDo - write the function here, a very explicit way of
/*engineering the recursion is to use this->operator()(...)*/
}
int max_sum; // I am now a member variable
};
Then instantiate FindSum find_sum;, set find_sum.max_sum if needed (perhaps even do that in a constructor), then call the overloaded () operator using find_sum(...).
This technique allows you to pass state into what essentially is a function.
From find_sum, return the so-far maximum sum (instead of void). That means that the recursion-terminating code would be:
if(index == combine.size()) {
int sum =0;
for(int i=0; i<index; ++i) {
sum += combine[i];
}
return sum;
}
and the recursive part would be
int max_sum = 0;
for(int i = start;
i < ar.size() && ar.size()-i > combine.size()-index;
++i) {
combine[index] = ar[i];
int thismaxsum = find_sum(ar, combine, index+1, start+1);
if(thismaxssum > max_sum)
max_sum = thismaxsum;
}
return max_sum;
So, the overall solution is:
#include <iostream>
#include <vector>
int find_sum(const std::vector<int>& ar, std::vector<int>& combine,
int index, int start);
int main() {
int N = 10;
int M = 3;
std::vector<int> ar(N);
ar = { 0,9,2,3,7,6,1,4,5,8 };
int index = 0, start = 0;
std::vector<int> combine(M);
int max_sum = find_sum(ar, combine, index, start);
std::cout << max_sum << std::endl;
return 0;
}
int find_sum(const std::vector<int>& ar, std::vector<int>& combine,
int index, int start)
{
if (index == combine.size())
{
int sum = 0;
for (int i = 0; i<index; ++i)
{
sum += combine[i];
}
return sum;
}
int max_sum = 0;
for (int i = start;
i < ar.size() && ar.size() - i > combine.size() - index;
++i)
{
combine[index] = ar[i];
int thismaxsum = find_sum(ar, combine, index + 1, start + 1);
if (thismaxsum > max_sum)
max_sum = thismaxsum;
}
return max_sum;
}
Global variables are much better then adding operands and variables to recursion functions because each operand and variable causes heap/stack trashing negatively impact performance and space usage risking stack overflow for higher recursions.
To avoid global variables (for code cosmetics and multi threading/instancing purposes) I usually use context or temp struct. For example like this:
// context type
struct f1_context
{
// here goes any former global variables and stuff you need
int n;
};
// recursive sub function
int f1_recursive(f1_context &ctx)
{
if (ctx.n==0) return 0;
if (ctx.n==1) return 1;
ctx.n--;
return (ctx.n+1)*f1_recursive(ctx.n);
}
// main API function call
int f1(int n)
{
// init context
f1_context ctx;
ctx.n=n;
// start recursion
return f1_recursion(ctx);
}
the f1(n) is factorial example. This way the operands are limited to single pointer to structure. Of coarse you can add any recursion tail operands after the context... the context is just for global and persistent stuff (even if I did use it for the recursion tail instead but that is not always possible).
Here is a simple case where I'm finding the Max of an Array.
Im attempting to use an auto iterator in a array passed into my function.
When I utilize the same code in my function body no error.
The reference inside the function max creates a compile error
cpp:7:14: error: invalid range expression of type 'int *'; no viable 'begin' function available
for (auto& x: array){
^ ~~~~~
Here is my current code, i included a reference to normal usage in "normalMax" and a inline main body function.
I want to know why the iterator in the 'max' function produces an error
#include <iostream>
//max num
//causes an error
int max(int* array){
int max = 0;
for (auto& x: array){
if (x >max)
max = x;
}
return max;
};
//normal behavior
int normalMax(int* array){
int max = 0;
for (int i=0; i<4; i++){
if (i >max)
max = i;
}
return max;
};
int main(){
int A[] = {1,2,3,4,5};
int B[] = {5,6,10,100};
int max = 0;
//Works no Error
for (auto& x: B){
if (x >max)
max = x;
}
std::cout <<max;
//100
normalMax(B);
//max(B);
//compile error
return 0;
}
If you want to pass an array to a function so you the compiler can deduce its length, you'll need to pass it as reference not via a [decayed] pointer:
template <std::size_t N>
int max(int const (&array)[N]) {
int max = 0;
for (auto& x: array) {
if (x >max) {
max = x;
}
}
return max;
}
As a side note: there is no semicolon after the definition of a function. Also, the function isn't particular useful as you should probably rather return the position of the maximum element rather than just its value: the position is determined implicitly anyway and may carry information. Of course, once you locate the correct position you should also return the proper best value which is actually the rightmost version of the maximum.
I am trying to compile my code in VS 2010 that compiles and works in gcc, but I get a weird error on a lambda expression:
std::function<double (size_t level, size_t q)> doLevel = [&](size_t level, size_t q)
{ //line 52
double thisLevelP = density(q, data[level]);
if(level==T-1) return thisLevelP;
if(level==t-1) return thisLevelP*A(q,state)*doLevel(level+1,state);
double continuation = 0.0;
for(size_t i=0; i<Q; ++i)
{
continuation += A(q, i)*doLevel(level+1, i);
}
return thisLevelP*continuation;
};
The error is:
Error 1 error C2086: 'size_t &_T' : redefinition c:\users\ga1009\documents\phd\cpp\pmi\cpp\test\baumiterationtest.cpp 52
Error 2 error C2661: '`anonymous-namespace'::`anonymous-namespace'::<lambda1>::<lambda1>' : no overloaded function takes 8 arguments c:\users\ga1009\documents\phd\cpp\pmi\cpp\test\baumiterationtest.cpp 52
What is wrong?
As seen in the comments above by chris, lambdas with multiple return statements need an explicit return type which can be declared like this ->double.
More importantly though the offending line is the variable named t which is captured by the lambda. I originally though this was a name clash but as STL correctly points out it happens with any two names which are the same except one is capital. This is a compiler bug which is known and has been fixed in the newest versions.
double density(std::size_t, int)
{
return 0;
}
double A(std::size_t, int)
{
return 0;
}
int main(int argc, char *argv[])
{
int data[] = {1,2,3};
std::size_t T = 1;
std::size_t t = 2; //<<<<< change this name and it compiles
std::size_t state = 3;
std::size_t Q = 4;
std::function<double (int,int)> doLevel = [&](int level, int q)->double
{
double thisLevelP = density(q, data[level]);
if(level==T-1)
return thisLevelP;
if(level==t-1)
return thisLevelP*A(q,state)*doLevel(level+1,state);
double continuation = 0.0;
for(size_t i=0; i<Q; ++i)
{
continuation += A(q, i)*doLevel(level+1, i);
}
return thisLevelP*continuation;
};
}
Help I don't understand why i can not run this snippet of code it is for a homework assignment and xCode seems to disagree with me when it says I havent defined the function. see bellow in main for the error
template <class Comparable>
Comparable maxSubsequenceSum1( const vector<Comparable> & a, int & seqStart, int & seqEnd){
int n = a.size( );
Comparable maxSum = 0;
for( int i = 0; i < n; i++ )
for( int j = i; j < n; j++ )
{
Comparable thisSum = 0;
for( int k = i; k <= j; k++ )
thisSum += a[ k ];
if( thisSum > maxSum )
{
maxSum = thisSum;
seqStart = i;
seqEnd = j;
}
}
return maxSum;
}
int main(){
vector<int> vectorofints;
vectorofints.resize(128);
for (int i=0; i<vectorofints.size(); i++){
vectorofints[i] = (rand() % 2001) - 1000;
}
maxSubsequenceSum1(vectorofints, 0, 127) //**---->the error i get in xcode is "No matching function for call to maxSubsequenceSum1"
return 0;
}
Change the signature from
Comparable maxSubsequenceSum1( const vector<Comparable> & a,
int & seqStart, int & seqEnd)
to
Comparable maxSubsequenceSum1( const vector<Comparable> & a,
int seqStart, int seqEnd)
The same problem happens if you would do int & i = 0;. You cannot initialize a non-const reference from an rvalue. 0 and 127 are temporary objects that expire at the end of the expression, temporaries cannot bind to non-const references.
You have declared a function that expects two integer references but the one you are calling takes two integers by value.
It should be like this
vector<int> vectorofints;
vectorofints.resize(128);
for (int i=0; i<vectorofints.size(); i++){
vectorofints[i] = (rand() % 2001) - 1000;
}
int k = 0;
int j = 127;
maxSubsequenceSum1(vectorofints, k, j)
return 0;
The compiler is correct. You are calling maxSubsequenceSum1(std::vector<int>&, int, int), you defined maxSubsequenceSum1(std::vector<int>&, int &, int &)
There are 2 quick solutions:
1) Redefine your function to not take a reference.
2) Move your constants to variables and pass them along that way.
Note: there is another problem with your code. You invoke the function maxSubsequenceSum1, but you do not tell it what template parameter to use.
I have been corrected, and the correction is correct. The note is not valid.