What is the Difference between using BOOST's ForEach and my own custom #define macro to iterate through a container??
mine:
#define iterate(i,x) for(typeof(x.begin()) i=x.begin();i!=x.end();++i)
boost:
#include <string>
#include <iostream>
#include <boost/foreach.hpp>
int main()
{
std::string hello( "Hello, world!" );
BOOST_FOREACH( char ch, hello )
{
std::cout << ch;
}
return 0;
}
Please explain which method is better and why?
First big difference, is when you using rvalues, like this:
vector<int> foo();
// foo() is evaluated once
BOOST_FOREACH(int i, foo())
{
}
// this is evaluated twice(once for foo().begin() and another foo().end())
iterate(i, foo())
{
}
This is because BOOST_FOREACH detects if it is an rvalue and makes a copy(which can be elided by the compiler).
The second difference is BOOST_FOREACH uses Boost.Range to retrieve the iterators. This allows it to be extended easily. So it will work on arrays and std::pair.
The third difference, is your iterate macro automatically deduces the type of the range, which can be very convenient on older compilers that support typeof but not auto. However, BOOST_FOREACH will work on all C++03 compilers.
Related
How can you concisely combine a container of std::string_views?
For instance, boost::algorithm::join is great, but it only works for std::string.
An ideal implementation would be
static std::string_view unwords(const std::vector<std::string_view>& svVec) {
std::string_view joined;
boost::algorithm::join(svVec," ");
return joined;
}
ITNOA
short C++20 answer version:
using namespace std::literals;
const auto bits = { "https:"sv, "//"sv, "cppreference"sv, "."sv, "com"sv };
for (char const c : bits | std::views::join) std::cout << c;
std::cout << '\n';
since C++23 if you want to add special string or character between parts you can just use simple join_with and your code is just below (from official cppreference example)
#include <iostream>
#include <ranges>
#include <vector>
#include <string_view>
int main() {
using namespace std::literals;
std::vector v{"This"sv, "is"sv, "a"sv, "test."sv};
auto joined = v | std::views::join_with(' ');
for (auto c : joined) std::cout << c;
std::cout << '\n';
}
Note1: if you do not like use not stable release of language, you can simple use range-v3 library for join_with views
Note2: As Nicol Bolas you cannot join literally to exact one string_view without any copy (you can copy to string and ... :D), if you want to know more detailed about that you can see Why can't I construct a string_view from range iterators? SO question and answer.
Is there some way in C++11 or higher to achieve a similar behavior to:
int some_int;
std::string x=variable_name<some_int>::value; //Theoretical code
std::cout << x;
Result should be:
some_int
If not, is there a compiler specific way to do it? I am targeting MSVS.
You ask:
Is there some way in C++11 or higher to achieve a similar behavior to:
int some_int;
std::string x=type_name<some_int>::value; //Theoretical code
std::cout << x;
Result should be:
some_int
Yes, you can just use the preprocessor's stringizing operator #:
#include <iostream>
#define NAME_OF( v ) #v
using namespace std;
auto main() -> int
{
int some_int;
//std::string x=type_name<some_int>::value; //Theoretical code
auto x = NAME_OF( some_int );
(void) some_int;
cout << x << endl;
}
If you're asking for something different, then please post a new question since this one has now been answered (amending the question would invalidate this answer).
As an example real world usage, here's macro to pass a variable and its name to a test function:
#define TEST( v ) test( v, #v )
If you want a compile time check that the name in question is a variable or type name, then you can simply apply sizeof, e.g. in a comma expression:
#define NAME_OF( v ) (sizeof(v), #v)
The difference between having sizeof or not, is whether this is guaranteed to be done purely at compile time, versus possibly generating code to also do something at run time.
To avoid a possible warning you can add a pseudo-cast to void:
#define NAME_OF( v ) ((void) sizeof(v), #v)
And to make this work also for a function name you can add a typeid:
#define NAME_OF( name ) ((void) sizeof(typeid(name)), #name)
Complete example:
#include <typeinfo>
#define NAME_OF( name ) ((void) sizeof(typeid(name)), #name)
void foo() {}
#include <iostream>
using namespace std;
auto main() -> int
{
int some_int;
(void) some_int;
//std::string x=type_name<some_int>::value; //Theoretical code
auto v = NAME_OF( some_int );
auto t = NAME_OF( int );
auto f = NAME_OF( foo );
#ifdef TEST_CHECKING
(void) NAME_OF( not_defined );
#endif
cout << v << ' ' << t << ' ' << f << endl;
}
The checking is not 100% perfect, though, because it's still possible to pass a function invocation to the NAME_OF macro.
As others have pointed out, you can indeed use a macro to "stringify" the variable name. However, instead of simply defining it as #define NAMEOF(variable) #variable, you can use the following definition:
#define NAMEOF(variable) ((decltype(&variable))nullptr, #variable)
As you can see, it uses a comma operator. The left part of this expression does nothing but performs a (pointless) conversion from nullptr to a pointer to variable's type, the result of which gets immediately discarded. The right part simply returns the stringified variable's name.
Why is this better than simply using #variable in the macro?
Thanks to the decltype() operator, the whole thing will only compile if you pass a variable of some sort and not some arbitrary string or a literal to NAMEOF macro. Consider the following example:
double value = 523231231312.0095;
cout<< NAMEOF(value) << endl; // value
cout<< NAMEOF(value1) << endl; // Compiler error: 'value1' was not declared in this scope
cout<< NAMEOF(42) << endl; // Compiler error: lvalue required as unary '&' operand
Because of this, if during future refactoring you modify the name of value variable, you won't forget to also modify places, where you use its name, since compiler will scream at you, until you also fix every usage of NAMEOF for this variable.
Tested on MinGW-W64 (gcc v5.2.0)
In the comments, #iammilind and #Niall have suggested two other ways to define this macro, which don't rely on C++11-specific decltype() operator:
#define NAMEOF(variable) ((void*)&variable, #variable)
...or...
// Unlike other definitions, this one, suggested by #Niall,
// won't get broken even if unary & operator for variable's type
// gets overloaded in an incompatible manner.
#define NAMEOF(variable) ((void)variable, #variable)
// On the other hand, it accepts literals as parameters for NAMEOF,
// though this might be desired behaviour, depending on your requirements.
NAMEOF(42); // 42
Using such a macro with #Leon's suggestion, based on your comments, we get:
template<class T>
void foo(T var, const char* varname)
{
std::cout << varname << "=" << var << std::endl;
}
#define FOO(var) foo(var, NAMEOF(var))
int someVariable = 5;
FOO(someVariable); // someVariable = 5
FOO(nonExistingVariable); // compiler error!
As follows from the comments, you need it for passing into a function both the value of the variable and its name. This must be done with the help of a macro:
#include <iostream>
template<class T>
void foo(T var, const char* varname)
{
std::cout << varname << "=" << var << std::endl;
}
#define FOO(var) foo(var, #var)
int main()
{
int i = 123;
double d = 45.67;
std::string s = "qwerty";
FOO(i);
FOO(d);
FOO(s);
return 0;
}
Output:
i=123
d=45.67
s=qwerty
There are the atox, strtox and stox families that I know of, but I can't seem to find any iterator based string to int conversions in the Standard Library or Boost.
The reason I need them is because I am having a parser whose match result is a range referencing the input string. I might very well have an input string like
...8973893488349798923475...
^begin ^end
so I need 738934883 as an integer.
Of couse, I could first take begin and end to construct an std::string to use with any of above families, but I would very much like to avoid that overhead.
So my question: Is there anything in the Standard Library or Boost accepting iterators as input, or do I have to write my own.
Boost does actually support this, using the Lexical Cast library. The following code uses a substring range to parse the number without performing any dynamic allocation:
#include <boost/lexical_cast.hpp>
#include <string>
#include <iostream>
int convert_strings_part(const std::string& s, std::size_t pos, std::size_t n)
{
return boost::lexical_cast<int>(s.data() + pos, n);
}
int main(int argc, char* argv[])
{
std::string s = "8973893488349798923475";
// Expect: 738934883
std::cout << convert_strings_part(s, 2, 9) << std::endl;
return 0;
}
The output (tested on OS X with Boost 1.60):
738934883
The lexical cast library has some great features for conversion to and from strings, though it isn't as well known as some of the others for some reason.
Until gavinb's answer, I was not aware of any such library function. My try would have been this, using any of atox and strtox as follows (you could avoid a dependency on boost library then, if wanted):
::std::string::iterator b; // begin of section
::std::string::iterator e; // end of section, pointing at first char NOT to be evaluated
char tmp = *e;
*e = 0;
int n = atoi(&*b);
*e = tmp;
If you only had const_iterators available, you would have to apply a const_cast to *e before modifying.
Be aware that this solution is not thread safe, though.
You could do it with strstream but it was depracated. Below two examples, with strstream and boost arrays:
http://coliru.stacked-crooked.com/a/04d4bde6973a1972
#include <iostream>
#include <strstream>
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/copy.hpp>
int main()
{
std::string in = "8973893488349798923475";
// ^^^^^
auto beg = in.begin()+2;
auto end = in.begin()+6;
// strstream example - DEPRECATED
std::istrstream os(&*beg, end-beg);
int n;
std::string ss;
os >> n;
std::cout << n << "\n";
// Boost example
namespace io = boost::iostreams;
int n2;
io::array_source src(&*beg, end-beg);
io::stream<io::array_source> os2(src);
os2 >> n2;
std::cout << n2 << "\n";
return 0;
}
With modern STL implementations std::string(begin,end) is not that bad - SSO eliminates any allocations for strings, smaller than ~15 chars (22 for 64bit).
#include<iostream>
#include<string>
#include<iterator>
using namespace std;
int main()
{
string a("hello world");
for(auto it = a.begin(); it != a.end() && !isspace(*it); it++ )
{
*it = toupper(*it);
}
cout<<a;
}
There are two errors I get. One is as mentioned, "auto changes meaning in c++11" and the other is "!= operator not defined." Never had this problem before.
I only used the auto operator because the book suggested.
I'm a beginner, and getting back to learning after about 2 months.
Having trouble catching up.
Your code runs ok when compiled with -std=c++11, You may check it here.
You can add the option in Setting->Compiler->Have g++ follow the C++11 ISO C++ language standard [-std=C++11] in CodeBlocks.
As chris mentioned, using Range-based for loop is much better. It's closer to spirit of C++11
and it's easier to learn for beginners. Consider:
#include <string>
#include <iostream>
int main()
{
std::string s{"hello, world"}; // uniform initialization syntax is better
for (auto& c : s) // remember to use auto&
if (!isspace(c)) c = toupper(c);
cout << s << '\n'; // remember the last newline character
return 0;
}
-- Saeed Amrollahi Boyouki
Here is some C++ code I'm playing around with:
#include <iostream>
#include <vector>
#define IN ,
#define FOREACH(x,y) for(unsigned int i=0;i<y.size();i++) { x=y[i];
#define ENDFOREACH }
using namespace std;
int main()
{
vector<int> ints;
ints.push_back(3);
ints.push_back(4);
ints.push_back(5);
ints.push_back(6);
FOREACH(int item IN ints)
cout << item;
ENDFOREACH
return 0;
}
However, I get an error:
macro "FOREACH" requires 2 arguments, but only 1 given
The code compiles if I change the IN to a comma. How can I get the IN to take the place of a comma?
Update: for those interested, here is the final version, which, if I do say so myself, is quite nice.
#include <iostream>
#include <vector>
#define in ,
#define as ,
#define FOREACH_(x,y,z) \
y x; \
if(z.size()) x = z[0]; \
for(unsigned int i=0,item;i<z.size();i++,x=z[i])
#define foreach(x) FOREACH_(x)
using namespace std;
int main()
{
vector<int> ints;
ints.push_back(3);
ints.push_back(4);
ints.push_back(5);
ints.push_back(6);
foreach(item as int in ints)
{
cout << item << endl;
}
return 0;
}
Others have already explained why it doesn't compile as is.
In order to make it work you have to give that IN a chance to turn into a comma. For that you can introduce an extra level of "indirection" in your macro definition
#define IN ,
#define FOREACH_(x,y) for(unsigned int i=0;i<y.size();i++) { x=y[i];
#define FOREACH(x) FOREACH_(x)
#define ENDFOREACH }
In this case you'll have to use some substitute for comma (like your IN) and can no longer specify comma explicitly. I.e. now this
FOREACH(int item IN ints)
cout << item;
ENDFOREACH
compiles fine, while
FOREACH(int item, ints)
cout << item;
ENDFOREACH
does not.
The compiler doesn't expand the IN macro before it reads the arguments to FOREACH. In fact, I think this is intentional (so that you can pass a comma to a macro).
Unfortunately, you'll have to use FOREACH(int item, ints).
You could also #define IN (make it nothing) and then use FOREACH(int item, IN ints), which is not quite as nice, but is acceptable.
That said, you may just want to use STL or Boost for foreach, unless you specifically want to create your own.
Expansion for IN doesn't happen early enough in your example, but you can pass the expanded version to another macro:
#define FOREACH(x) DO_FOREACH(x)
#define DO_FOREACH(x,y) for( ... ) ...
#define IN ,
#define XFOREACH(x,y) for(unsigned int i=0;i<y.size();i++) { x=y[i];
#define FOREACH(x) XFOREACH(x)
#define ENDFOREACH }
As previous posters have noted, the preprocessor does not expand macros in the arglist before it splits it into argument. However, as long as the macro doesn't use # or ##, it expands macros in the args before substituting them into the macro body, so an extra indirection does the trick
Check out BOOST_FOREACH - it does what you want
http://www.boost.org/doc/libs/1_35_0/doc/html/foreach.html
The preprocessor doesn't expand the IN to a comma until after it reads the arguments to FOREACH.
I'm pretty sure that the c++ preprocessor is one pass only, so you'll have to use:
FOREACH(int item, ints)
cout << item;
ENDFOREACH