using boost foreach with items that are themselves templates - c++

I have a std::deque< std::pair<int, int> > that I would like to iterate over using BOOST_FOREACH.
I tried the following:
#define foreach_ BOOST_FOREACH
// declaration of the std::deque
std::deque< std::pair<int, int> > chosen;
foreach_( std::pair<int,int> p, chosen )
{
...
}
But when I compile this (in Visual Studio ) I get the following errors:
warning C4002: too many actual parameters for macro 'BOOST_FOREACH'
1>c:\users\beeband\tests.cpp(133): error C2143: syntax error : missing ')' before '>'
1>c:\users\beeband\tests.cpp(133): error C2059: syntax error : '>'
1>c:\users\beeband\tests.cpp(133): error C2059: syntax error : ')'
1>c:\users\beeband\tests.cpp(133): error C2143: syntax error : missing ';' before '{'
1>c:\users\beeband\tests.cpp(133): error C2181: illegal else without matching if
What is the correct way to use BOOST_FOREACH with this deque?

The problem is the , as it is being used by the preprocessor to separate the macro arguments.
Possible solutions using typedef:
typedef std::pair<int, int> int_pair_t;
std::deque<int_pair_t> chosen;
foreach_( int_pair_t p, chosen )
// Or (as commented by Arne Mertz)
typedef std::deque<std::pair<int, int>> container_t;
container_t chosen;
foreach_(container_t::value_type p, chosen)
Possible replacements, both introduced in c++11, are:
range-for loop:
for (auto& : chosen)
{
}
lambdas:
std::for_each(std::begin(chosen),
std::end(chosen)
[](std::pair<int, int>& p)
{
});

As the author of BOOST_FOREACH, I ask you to please stop using it. It was a hack whose time has come and gone. Please, please, please use C++11's range-base for loops and let BOOST_FOREACH die.

Boosts foreach is a macro, which means it's handled by the preprocessor. And the preprocessor is pretty simple, and can't handle symbols with commas in them as it is used as a macro argument separator.

Related

error C2146: syntax error : missing ',' before identifier mType when passing a map by function

When I declare the below function:
#include <vector>
#include <map>
void setTypeByBanknote(tsBanknotes &tsBanknotes, std::map<char, std::vector<byte>> &mType);
My compiler shows the following error:
error C2146: syntax error : missing ',' before identifier mType
But if I do the following:
#include <vector>
#include <map>
typedef std::vector<byte> tvByteVector;
void setTypeByBanknote(tsBanknotes &tsBanknotes, std::map<char, tvByteVector &mType);
My compiler does not show any error and compiles correctly
Is there any way to pass this map as an argument without using typedef ?
I'm using visual 6.0 as IDE, I know it is very old. Is the problem because of the old IDE ? I do include vector and map libraries.
Thanks in advance!
std::map<char, std::vector<byte> >
^^^^
You need a space between two >s like > >. Otherwise VS 6.0, which is very old, gets confused with operator >>. It's better to update the compiler.

error in array sorting using vectors in VC++6 while no error in VC++2012

I used this line code in VC++2012 to sort integrated row array called arrayCosts.
This code work in this version but d not work at VC++6 version.
vector< vector<float> > my_vector ;
for( const auto& row : arrayCosts ) my_vector.push_back( vector<float>( begin(row), end(row) ) ) ;
sort( begin(my_vector), end(my_vector),
[]( const vector<float>& a, const vector<float>& b ) { return a[1] < b[1] ; } ) ;
The errors in VC++6 is as following.
e:\logistics\projects\10\10\source1.cpp(190) : error C2143: syntax error : missing ',' before ':'
e:\logistics\projects\10\10\source1.cpp(190) : error C2530: 'row' : references must be initialized
e:\logistics\projects\10\10\source1.cpp(190) : error C2059: syntax error : ':'
e:\logistics\projects\10\10\source1.cpp(191) : error C2065: 'begin' : undeclared identifier
e:\logistics\projects\10\10\source1.cpp(191) : error C2065: 'end' : undeclared identifier
e:\logistics\projects\10\10\source1.cpp(192) : error C2059: syntax error : '['
e:\logistics\projects\10\10\source1.cpp(192) : error C2143: syntax error : missing ')' before '{'
e:\logistics\projects\10\10\source1.cpp(192) : error C2143: syntax error : missing ';' before '{'
e:\logistics\projects\10\10\source1.cpp(192) : error C2065: 'a' : undeclared identifier
e:\logistics\projects\10\10\source1.cpp(192) : error C2109: subscript requires array or pointer type
e:\logistics\projects\10\10\source1.cpp(192) : error C2065: 'b' : undeclared identifier
e:\logistics\projects\10\10\source1.cpp(192) : error C2109: subscript requires array or pointer type
You're trying to use language features from 2011 with a compiler from 1997. That's not going to work.
You might have more success if you stick to C++98; although since your compiler predates even that, there's no guarantee that this would work.
// Define a comparison functor, to replace the lambda.
// This must be defined outside a function, for arcane reasons.
struct comparator {
bool operator()(const vector<float>& a, const vector<float>& b) {
return a[1] < b[1];
}
};
vector< vector<float> > my_vector ;
// Use an old-school for loop; range-based loops didn't exist back then,
// and neither did "auto" type deduction.
// (This assumes arrayCosts is also a vector<vector<float>>;
// change the iterator type if it's something else).
for (vector< vector<float> >::const_iterator it = arrayCosts.begin();
it != arrayCosts.end(); ++it)
{
// std::begin and std::end didn't exist either
my_vector.push_back( vector<float>( it->begin(), it->end() ) ) ;
}
// Again, no std::begin or std::end.
sort(my_vector.begin(), my_vector.end(), comparator());

What's the typedef syntax for an array type?

I have this C++11 code:
using swallow = int[];
but MSVS2013 Preview barfs on it:
error C2143: syntax error : missing ';' before '='
So I tried
typedef int[] swallow;
But that got me:
warning C4091: 'typedef ' : ignored on left of 'int' when no variable is declared
So I tried reversing the typedef stuff, as I never remember (hence the reason using is so great):
typedef swallow int[];
And got:
m:\development\source\ambrosia\libambrosia\Ambrosia/utility.h++(33) : error C2144: syntax error : 'int' should be preceded by ';'
I'm already disappointed in MSVS2013. How can I write this so the MS compiler will understand this simple code?
typdef is a declaration, and follows the same syntax as a declaration:
extern int a[];
typedef int b[];
(Note that b is an incomplete type, and that a is only declared, not defined.)

Strange behaviour with templates and #defines

I have the following definitions:
template<typename T1, typename T2>
class Test2
{
public:
static int hello() { return 0; }
};
template<typename T>
class Test1
{
public:
static int hello() { return 0; }
};
#define VERIFY_R(call) { if (call == 0) printf("yea");}
With these, I try to compile the following:
VERIFY_R( Test1<int>::hello() );
this compiles fine
VERIFY_R( (Test2<int,int>::hello()) );
this also compiles fine, notice the parentheses around the call.
VERIFY_R( Test2<int,int>::hello() );
This, without the parentheses produces a warning and several syntax errors:
warning C4002: too many actual parameters for macro 'VERIFY_R'
error C2143: syntax error : missing ',' before ')'
error C2059: syntax error : ')'
error C2143: syntax error : missing ';' before '}'
error C2143: syntax error : missing ';' before '}'
error C2143: syntax error : missing ';' before '}'
fatal error C1004: unexpected end-of-file found
What's going on here?
This happens with VS2008 SP1.
The comma inside a macro can be ambiguous: an extra set of parentheses (your second example) is one way of disambiguating. Consider a macro
#define VERIFY(A, B) { if ( (A) && (B) ) printf("hi"); }
then you could write VERIFY( foo<bar, x> y ).
Another way of disambiguating is with
typedef Test1<int,int> TestII;
VERIFY_R( TestII::hello() );
The preprocessor is a dumb text replacement tool that knows nothing about C++. It interprets
VERIFY_R( Test1<int,int>::hello() );
as
VERIFY_R( (Test1<int), (int>::hello()) );
which calls VERIFY_R with too many parameters. As you noted, additional parentheses fix this:
VERIFY_R( (Test1<int,int>::hello()) );
The question remains, however, why you need the preprocessor anyway. The macro you used in your question could just as well be an inline function. If you real code doesn't do anything requiring the preprocessor, try to get rid of macros. They just cause pain.
The comma in <int, int> is treated as an argument separator for the macro, rather than for the template. The compiler therefore thinks you're calling VERIFY_R with two arguments (Test1<int and int>::hello()), when it requires only one. You need to use variadic macros to expand everything supplied to the macro:
#define VERIFY_R(...) { if ((__VA_ARGS__) == 0) printf("yea");}
It is generally a good idea to wrap macro arguments in parentheses, as well, to prevent other kinds of weird substitution errors.
The preprocessor doesn't know that < and > are supposed to be brackets, so it interprets the expression as two macro arguments, Test1<int and int>::hello(), separated by the ,. As you say, it can be fixed by surrounding the entire expression with parentheses, which the preprocessor does recognise as brackets.
I'm not sure if this is an error in your reporting here or the actual problem, but your last VERIFY_R is still referencing Test1, rather than Test2.

Why does the order of my #includes matter? (C++)

I've created a header file called "list_dec.h", put it in a folder "C:\Headers", and set my compiler to include files from "C:\Headers", so now I can do things like
#include<list_dec.h>
int main(){return(0);}
but when I try to do something like
#include<iostream>
#include<list_dec.h>
int main(){return(0);}
I get an error (not anything specific, just a huge list of syntax errors in "list_dec.h", which I know aren't real because I've been able to compile it as both a main.cpp file and a .h file in a separate project). However, when I change to order so "list_dec.h" is on top:
#include<list_dec.h>
#include<iostream>
int main(){return(0);}
all of the errors go away. So why does the order of the error matter?
NB: As far as I know, this occurs when I use "list_dec.h" with all header files, but the files I'm absolutely positive it occurs in are:
#include<iostream>
#include<vector>
#include<time.h>
#include<stdlib.h>
EDIT: These are the errors I get when "list_dec.h" is below any other header:
c:\headers\list_dec.h(14) : error C2143: syntax error : missing ')' before 'constant'
c:\headers\list_dec.h(51) : see reference to class template instantiation 'list<T,limit>' being compiled
c:\headers\list_dec.h(14) : error C2143: syntax error : missing ';' before 'constant'
c:\headers\list_dec.h(14) : error C2059: syntax error : ')'
c:\headers\list_dec.h(14) : error C2238: unexpected token(s) preceding ';'
c:\headers\list_dec.h(69) : warning C4346: 'list<T,limit>::{ctor}' : dependent name is not a type
prefix with 'typename' to indicate a type
c:\headers\list_dec.h(69) : error C2143: syntax error : missing ')' before 'constant'
c:\headers\list_dec.h(69) : error C2143: syntax error : missing ';' before 'constant'
c:\headers\list_dec.h(69) : error C2988: unrecognizable template declaration/definition
c:\headers\list_dec.h(69) : error C2059: syntax error : 'constant'
c:\headers\list_dec.h(69) : error C2059: syntax error : ')'
c:\headers\list_dec.h(78) : error C2065: 'T' : undeclared identifier
c:\headers\list_dec.h(78) : error C2065: 'limit' : undeclared identifier
c:\headers\list_dec.h(78) : error C2065: 'T' : undeclared identifier
c:\headers\list_dec.h(78) : error C2065: 'limit' : undeclared identifier
c:\headers\list_dec.h(79) : error C2143: syntax error : missing ';' before '{'
c:\headers\list_dec.h(79) : error C2447: '{' : missing function header (old-style formal list?)
If it helps, these are the lines mentioned in the errors (14, 69, 78, and 79):
Line 14: list(const T& NULL); (A constructor for "list" class)
Line 69: inline list<T, limit>::list(const T& NULL): (Definition for the constructor, also, the colon at the end is intentional, It part of the definion ie: void x(int n): VAR(n).)
Line 78: inline list<T, limit>::list(const list<T, limit>& lst) (def for the copy constructor)
Line 79: { (the begining of the list-copy contructor)
And a lot of people want to see the beginning of "list_dec.h":
template<class T, size_t limit>
class list
NB: These aren't the first lines, but they're where I think the problem is, the lines before them are simply an enumeration called "err".
EDIT: Just a note, "list_dec.h" contains no includes, defines, ifdefs, or anything precede with a '#'. Besides the enumeration, it only contains the "list" class declaration and the "list" class member function definitions.
Generally speaking it should not, however it may be possible for there to be conflicting definitions of symbols or preprocessor macros that end up confusing the compiler. Try to narrow down the size of the problem by removing pieces and includes from the conflicting header until you can see what is causing it.
In response to the error messages you posted, the symbol NULL is often implemented as a preprocessor macro for the number 0. This is so that you can easily use it as a null pointer. Therefore this:
list(const T& NULL);
Could be converted into this syntax error by the preprocessor:
list(const T& 0);
Change the name of the parameter to something other than NULL.
Note that here:
Line 14: list(const T& NULL); (A constructor for "list" class)
NULL is the name of standard macro - when a standard header file is included before list_dec.h it will most likely cause NULL to be defined which will in turn cause your code to look something like this to the compiler:
list(const T& 0);
The constant 0 above makes the line ill-formed C++. You might get more information by instructing your compiler to produce preprocessed output file.
Presumably list_dec.h is running into a macro that's defined in those other headers (or some headers they in turn include) -- hard to say which one without seeing the first error message and the relevant part of list_dec.h!
The actual errors would give a more specific clue, bt it means there's something in your include file that is screwing up the scan for the next one. The most common thing would be some kind of unclude #-directive, like a #if missing its #endif.
If the errors are random in nature, it could be a missing semi colon. The compiler will usually halt on that, but on occasion you get "lucky".
Otherwise, conflicting names or defines. Do you have anything named std for example?