Lambda expressions in VS 2010 as opposed to gcc - c++

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;
};
}

Related

Why The problem in void error with "return" -fpermissive

Cannot understand what is the problem. There is an error: return-statement with a value, in function returning ‘void’ [-fpermissive]
return result;
#include <iostream>
#include <vector>
using namespace std;
void print(const vector<int>& v)
{
int N = 2;
vector<int> result(v.size());
size_t pos = 0;
for (size_t i = 0;i < v.size(); i++)
{
pos = i*N;
if (pos >= v.size()) pos %= (v.size());
result[i] = v[pos];
}
return result;
}
int main()
{
vector<int> v{1, 2, 3, 4, 5, 6};
print(v);
return 0;
}```
The problem is that you have declared that the function returns void. This means that the function doesn't return a value. However, you also have a return statement that returns a value. Returning a value from a function that doesn't return a value is a contradiction. This is a violation of rules of the language and the program is ill-formed.
Ways to fix this bug are:
Either change the declaration of the function so that the return type matches the type of the value given to the return statement.
Or remove the return statement.

strange behavior of constexpr

I'm trying to understand constexpr as best as I can. However, i've found a problem that I can't really explain (I don't understand the compiler's decisions on this code-piece). This code has been compiled with the -O3 flag on X86-64 gcc 7.2, with C++17 as it's std flag (I've been using godbolt.org for this compilation)
Taking this code:
#include <stdlib.h>
#include <stdio.h>
template <size_t N>
class constexpr_sum_array_compile_time
{
public:
inline constexpr constexpr_sum_array_compile_time ()
{
start_arr();
sum();
}
inline constexpr void start_arr()
{
for (int i = 0; i<N; ++i)
{
m_arr[i] = i;
}
}
inline constexpr void sum()
{
m_sum = 0;
for (int i = 0; i<N; ++i)
{
m_sum += m_arr[i];
}
}
constexpr int sum_res()
{
return this->m_sum;
}
private:
int m_arr[N];
int m_sum = 0;
};
#define NUMBER (4)
int main()
{
return constexpr_sum_array_compile_time<NUMBER>().sum_res();
}
In a nutshell, this is a constexpr class that creates an array with a given size, and then sums an array with incremental values (arr[0] = 0, arr[1] = 1, arr[2] = 2... arr[n] = n) on compile_time (at least thats what I want it to do).
If the "NUMBER" define is in range: { 0 <= NUMBER <= 4 or 8 <= NUMBER <= 71 }
Then this class is optimized completely and returns only a single value (Like expected)
However! If NUMBER is in range: { 5 <= NUMBER <= 7 or NUMBER >= 72}, the compiler ISN'T ABLE to optimize the return value.
How come? What's so special about these values?
You can check the optimizations over at godbolt.org, it shows raw assembly as it's being compiled.
SOLVED
It seems like I needed to create a variable that holds the keyword of constexpr in order to allow the compiler to calculate it in compile time. The new code is:
#include <stdlib.h>
#include <stdio.h>
template <size_t N>
class constexpr_sum_array_compile_time
{
public:
inline constexpr constexpr_sum_array_compile_time() : m_arr(), m_sum(0)
{
start_arr();
sum();
}
inline constexpr void start_arr()
{
for (int i = 0; i<N; ++i)
{
m_arr[i] = i;
}
}
inline constexpr void sum()
{
m_sum = 0;
for (int i = 0; i<N; ++i)
{
m_sum += m_arr[i];
}
}
inline constexpr int sum_res()
{
return this->m_sum;
}
private:
int m_arr[N];
int m_sum;
};
#define NUMBER (6)
int main()
{
constexpr auto res = constexpr_sum_array_compile_time<NUMBER>().sum_res();
return res;
}
Now no matter what I write in NUMBER (even 100000) it shows the value optimized and calculated at compile-time!
Contrary to your expectation your class is not constexpr (and not used in constexpr expression).
constexpr auto res = constexpr_sum_array_compile_time<NUMBER>().sum_res();
would show you the different errors you have.
So what you observe with assembly is just regular optimization.

std::bind used in function template issue

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

Referencing Auto Array Iterator in function

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.

"No matching function for call to" Templates C++

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.