I am currently rewriting a small project i written some time ago, and am replacing function pointers with std::function and lambdas.
While doing this i stumbled over an issue with for loops in lambdas.
in Visual Studio 2010 (with SP1) generates strange errors when for loops are used inside lambdas, IF the lambda is defined at file scope:
#include <iostream>
auto print_sum =
[]( int n )
{
int sum=0;
// line below generates:
// error C2143: syntax error : missing ')' before ';'
for( int i=1; i<=n; ++i )
sum += i;
std::cout << sum << "\n";
};
int main()
{
print_sum(3);
return 0;
}
following snippet however compiles fine:
#include <iostream>
int main()
{
auto print_sum =
[]( int n )
{
int sum=0;
for( int i=1; i<=n; ++i )
sum += i;
std::cout << sum << "\n";
};
print_sum(3);
return 0;
}
Both snippets compile fine using MinGW GCC 4.7.
Has anyone else observed this behaviour aswell?
Is this a bug in the lambda implementation of the Visual Studio?
Do you know any workarounds?
Edit:
bug report on microsoft connect:
https://connect.microsoft.com/VisualStudio/feedback/details/660742/error-with-for-loops-in-file-scope-lamdas-c-0x#details
I can verify this behavior on Visual Studio 2010 RTM. It appears to be limited to just for loops as the following compiles just fine.
auto print_sum =
[](int n)
{
int sum=0;
int i = 1;
while (i <= n)
{
sum += i;
i++;
}
std::cout << sum << "\n";
};
I would definitely alert microsoft to this issue by filing a bug on connect
http://connect.microsoft.com
Note: I don't 100% know if this is a bug but evidence suggests that it is
Related
#include <vector>
#include <cmath>
void print(std::vector <int> const& a) {
for (int i = 0; i < a.size(); i++) {
std::cout << a.at(i) << " ";
}
}
std::vector<int> factors(int n) {
std::vector<int> vec = {};
for (int i = 0; i < round(sqrt(n)); i++) {
if (size(factors(i)) == 0) {
vec.push_back(i);
}
std::cout << i;
}
return vec;
}
int main() {
std::vector<int> vec = factors(600851475143);
print(vec);
}
This is my C++ code for Project Euler #3.
New to C++, so my code might be completely wrong syntactically, however I am not getting any build errors (using Visual Studio).
Not getting any output however. I understand this could be my fault, and the program might just be running extremely slow. But I programmed this in python using the same iterative method and it worked perfectly with a fast runtime.
Edit:
I am however getting this message in the console:
D:\RANDOM PROGRAMMING STUFF\PROJECTEULER\c++\projecteuler3\x64\Debug\projecteuler3.exe (process 13552) exited with code 0.
Press any key to close this window . . .
If you enable your compiler warnings, you should see an overflow warning
prog.cc: In function 'int main()':
prog.cc:23:36: warning: overflow in conversion from 'long int' to 'int' changes value from '600851475143' to '-443946297' [-Woverflow]
23 | std::vector vec = factors(600851475143);
so what gets passed to factors is not 600851475143 but -443946297
Of course Gaurav has given the correct answer. This is how to fix it, change from int to unsigned long long, to allow for the biggest integers possible that are supported without any external libraries
#include <cmath>
#include <iostream>
#include <vector>
void print(std::vector<int> const& list){
for( auto const& item : list){
std::cout << item << "\n";
}
}
std::vector<int> factors(unsigned long long n) {
std::vector<int> vec = {};
for( int i = 0; i < std::round(std::sqrt(n)); ++i ){
if( factors(i).empty() ) {
vec.push_back(i);
}
//std::cout << i << ", ";
}
return vec;
}
int main() {
std::vector<int> vec = factors(600851475143ULL);
print(vec);
}
I have also done some other minor changes:
Change the foor loop of print to a rang-based for loop
Added a delimeter i printing
added std:: namespace to functions
replaced size(vec) == 0 with empty to improve readability
Another good habit is to compile with -Wall to enable more warnings and -Werror so you are actually forced to take care of all warnings instead of brushing them off.
I am trying to use a 128 data type "__int128_t" in my VSCode while writing a C++ program, but I am getting an error saying identifier "__int128_t" is undefined. However, it works perfectly on my friend's PC. I thought since he installed the MinGW GCC compiler recently so there must be an issue with my version as it is comparatively old as compared to his, so I updated my g++ to version 11.2.0. Still, even after this, "__int128_t" is not working in my C++ program which I am writing in VS Code. This is my code.
#include <bits/stdc++.h>
using namespace std;
void fastIO()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
}
int main()
{
fastIO();
long long input[100000], n;
cin >> n;
__int128_t sum1 = (n * (n + 1)) / 2;
__int128_t sum2 = 0;
for (int i = 0; i < n - 1; i++)
{
cin >> input[i];
sum2 += input[i];
}
cout << sum1 - sum2;
return 0;
}
I seem to get an erroneous warning message from Visual Studio 2019 (16.5 Preview but also in 16.4 and earlier) Code Analysis tool. Is this a bug, or am I really just missing something?
The warning generated (exactly) is:
warning C6385: Reading invalid data from 'prodlist': the readable size is '(size_t)*32+8' bytes, but '64' bytes may be read.
Here's the code which generates the warning (as minimal as possible)
#include <cstdint>
#include <string>
#include <iostream>
struct Product {
std::string price_profile;
};
int getNumRows() {
return 5;
}
Product *getProductsFromDB( int &numelements ) {
numelements = 0;
const int num_rows = getNumRows();
if ( num_rows == 0 ) {
numelements = 0;
return nullptr;
}
Product *prodlist = new Product[num_rows];
for ( int i = 0; i < num_rows; ++i ) {
prodlist[i].price_profile = "test"; // Warning on this line
}
numelements = num_rows;
return prodlist;
}
int main() {
int num_rows;
Product *prodlist = getProductsFromDB( num_rows );
for ( int i = 0; i < num_rows; ++i ) {
std::cout << prodlist[i].price_profile;
}
getchar();
}
If I change the price_profile to an int (and its corresponding value), or if I change num_rows to a constant (like 5) then the warning goes away.
It seems in Visual Studio 2019 Microsoft is enforcing SAL analysis rules on C and C++ code by default, even though there are still plenty of false positives like your case here.
One thing you can do for now is disable the warning giving a false positive:
#pragma warning(push)
#pragma warning(disable:6385)
Product *getProductsFromDB( int &numelements ) {
...
}
#pragma warning(pop)
Consider the following code snippet:
#include <iostream>
#include <ctime>
#include <vector>
#include <list>
using namespace std;
#define NUM_ITER 100000
int main() {
clock_t t = clock();
std::list< int > my_list;
std::vector< std::list< int >::iterator > list_ptr;
list_ptr.reserve(NUM_ITER);
for(int i = 0; i < NUM_ITER; ++i) {
my_list.push_back(0);
list_ptr.push_back(--(my_list.end()));
}
while(my_list.size() > 0) {
my_list.erase(list_ptr[list_ptr.size()-1]);
list_ptr.pop_back();
}
cout << "Done in: " << 1000*(clock()-t)/CLOCKS_PER_SEC << " msec!" << endl;
}
When I compile and run it with visual studio, all optimizations enabled, I get the output:
Done in: 8 msec!
When I compile and run it with g++, using the flags
g++ main.cpp -pedantic -O2
I get the output
Done in: 7349 msec!
Which is rougly 1000 times slower. Why is that? According to the "cppreference" calling erase on a list is supposed to use up only constant time.
The code was compiled and executed on the same machine.
It might be that the implementation shipped by GCC doesn't store the size, and the one MSVC ships does. In this case the inner loop is O(n^2) with GCC, O(n) for MSVC.
Anyway, C++11 mandates that list::size is constant time, you may want to report this as a bug.
UPDATE Workaround:
You can avoid calling size() so many times:
size_t my_list_size = my_list.size();
while(my_list_size > 0) {
accum += *list_ptr[list_ptr.size()-1];
my_list.erase(list_ptr[list_ptr.size()-1]);
--my_list_size;
list_ptr.pop_back();
}
Now it reports 10 msec.
EDIT
Their list implementation isn't as efficient. I tried by replacing with:
#include <iostream>
#include <ctime>
#include <boost/container/vector.hpp>
#include <boost/container/list.hpp>
using namespace std;
#define NUM_ITER 100000
int main() {
clock_t t = clock();
boost::container::list< int > my_list;
boost::container::vector< boost::container::list< int >::iterator > list_ptr;
list_ptr.reserve(NUM_ITER);
for(int i = 0; i < NUM_ITER; ++i) {
my_list.push_back(rand());
list_ptr.push_back(--(my_list.end()));
}
unsigned long long volatile accum = 0;
while(my_list.size() > 0) {
accum += *list_ptr[list_ptr.size()-1];
my_list.erase(list_ptr[list_ptr.size()-1]);
list_ptr.pop_back();
}
cout << "Done in: " << 1000*(clock()-t)/CLOCKS_PER_SEC << " msec!" << endl;
cout << "Accumulated: " << accum << "\n";
}
This now runs in ~0ms on my machine, vs. ~7s using std::list on the same machine.
sehe#desktop:/tmp$ ./test
Done in: 0 msec!
Accumulated: 107345864261546
I'm implementing the MERGE SORT algorithm. I use std::list < int > as my list of input numbers. This is my code:
#include <iostream>
using namespace std;
#include <list>
void MergeSort(list<int> _list)
{
if (_list.size() > 1)
{
list<int> left;
list<int> right;
int mid = (0+_list.size())/2;
list<int>::iterator i = _list.begin();
for (int j = 0; j<mid; j++) ++i;
left.assign(_list.begin(),++i);
right.assign(i, _list.end());
MergeSort(left);
MergeSort(right);
_list.merge(left,right);
}
return;
}
int main()
{
list<int> myList;
myList.push_front(38);
myList.push_back(27);
myList.push_back(43);
myList.push_back(3);
myList.push_back(9);
myList.push_back(82);
myList.push_back(10);
cout << "Before sorting:\n";
list<int>::iterator i;
for(i=myList.begin(); i != myList.end(); ++i) cout << *i << " ";
// Merge Sort Function
MergeSort(myList);
//
cout << "\nAfter sorting:\n";
for(i=myList.begin(); i != myList.end(); ++i)
{
cout << *i << " ";
}
system("pause");
return 0;
}
But I builded this source file on Visual Studio 2012 and got this error: error C2064: term does not evaluate to a function taking 2 arguments (file)c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility (line)595
This is the first time i've dealed with this error and I have no idea how to fix it... Hope you guys can help me with this, thanks so much in advanced !
You are not using list<int>::merge correctly in the expression _list.merge(left, right);
check the documentation for merge function. There you can also find an example on how to use it.