Building cURLpp 0.7.2
I want to use cURLpp for a project I've been working on, but there's no package for Ubuntu.
I downloaded the tarball, but discovered that example 18 would not compile. It would fail with the following error:
example18.cpp: In function ‘int main(int, char**)’: example18.cpp:85: error: ‘BoostWriteFunction’ is not a member of ‘cURLpp::Options’ example18.cpp:85: error: ‘test’ was not declared in this scope example18.cpp:85: error: expected type-specifier example18.cpp:85: error: expected `;' make[1]: *** [example18.o] Error 1
I discovered that usage of the Boost
libraries was an option, and wasn't being tested for in example
18. boost::bind is one of the tools I frequently use in
C++, the Boost support seems less optional to me, so I cleaned and ran
configure --with-boost. Still, I got the error.
It became clear that the configure-generated config.h was not being included. This patch fixed that, and fixed the compile:
--- ../../curlpp-0.7.2-orig/curlpp/global.h 2007-09-22 09:31:10.000000000 -0500 +++ global.h 2009-04-05 10:57:58.000000000 -0500 @@ -26,6 +26,8 @@ #ifndef HAVE_CONFIG_H #include "config.win32.h" +#else +#include "config.h" #endif #endif
Comments: 2
GCD Via C++ Template Metaprogramming
Via IRC:
09:06 < jepler> michael: c++ template metaprogramming puzzle
09:06 < jepler> I want a template class gcd<a,b> so that
gcd<a,b>::value == gcd(a,b)
09:07 < jepler> actually I bet it's pretty simple
It turns out Jeff's right; it's pretty simple.
#include <iostream>
template<int A, int B>
struct GCD { enum { value = GCD<B,A%B>::value }; };
template<int A> struct GCD<A,0> { enum { value = A }; };
int main() {
std::cout << GCD<N1,N2>::value << "\n";
return 0;
}
To run it, you compile it, defining N1 and N2 on the command line, and run the resulting program, which prints the result of the calculation GCD(N1,N2), which was performed at compile time. Neat!
~$ g++ -DN1=293888 -DN2=4837888 gcd.cc && ./a.out
512
~$
Comments: 0
Erasing Elements from a Map: A Mini-Pattern
It's a reality of programming in C++ that all containers are not created equal, and do not receive equal protection under the algorithms. Or something.
Today at work, for example, I needed to scan a std::map,
and erase elements from it for which some predicate was true. The
typical way to remove an element from a map is to use the map's erase
method. There is an erase method that takes a range (a start and end
iterator), but no way to perform the erase based on the result of a
predicate. That is, there's no map::erase_if.
For sequence containers, there exists an algorithm,
std::remove_if(start, end, pred), but it operates by
reordering the elements of the range it's operating on, by assigning an
element from one position to another with operator=.
Because the first element of the pair that comprises a map::value_type,
the key, is const, it can't be assigned to.
typedef std::map<T,U> Map;
typedef Map::value_type Value;
extern bool predicate(const Value &v);
Map m;
// Wrong: compile error.
std::remove_if(m.begin(), m.end(), std::ptr_fun(predicate));
The next obvious thing to try is an explicit loop, with an explicit branch based on the predicate. The naïve implementation, though, will have problems.
for(Map::iterator i = m.begin(); i != m.end(); i++) {
if(predicate(*i))
m.erase(i); // ONOZ!
}
ONOZ!
because after the call to m.erase(i),
i is no longer valid: it refers to memory that has been
released. I suspect the increment clause of the for-statement puts us in
nasal
demon territory, but I'm not sure what the standard says.
To be honest, I knew the above constructs were wrong, but I didn't know if there was an idiom to get the behavior I wanted. After some research and some experimenting, the following is the construct I decided to use.
for(Map::iterator i = m.begin(); i != m.end(); /* increment in body */ ) {
Map::iterator current = i++;
if(predicate(*current))
m.erase(current);
}
Comments: 2
ICU4C, FreeBSD 5.3, U_REGEX_MISMATCHED_PAREN: A Fix
I've come up with a fix for the U_REGEX_MISMATCHED_PAREN problem in ICU running on FreeBSD 5.3. I removed an entire type, and some casts to that type. I've tested on FreeBSD, Red Hat 9, and Ubuntu Dapper Drake, all passing the included tests with flying colors.
I haven't figured out why yet, but the cast of
doOpenNonCaptureParen to EParseAction at
i18n/regexcmp.cpp:345 was yielding 0. While digging in to
this, I discovered that EParseAction was only used as the
type for the single parameter to
RegexCompile::doParseActions. (It's used in
rbbiscan.cpp, too, but that's unrelated code, with a separate
definition of the enum.) To reduce complexity, I tried passing a
int32_t to doParseActions and
stripping out the casts. That did the trick.
I assume that in 3.8, there will be a more comprehensive solution, but for now, this works.
The patches:
Comments: 1