Posts Tagged ‘c#’
C++ test for within
Thursday, August 26th, 2010I found myself having to right a bunch of range checking code like this:
val = 1.0;
so I wrote this simple function.
template
const Type & within (const Type &lower, const Type &val, const Type &upper)
{
return std::min (std::max (lower, val), upper);
}
So the above code gets simplified to:
I wasn’t happy about the extra copy being created but was willing to live with it.
Then I ran across this fragment which is so similar but ended up changing the final design:
val = 5;
The difference is the above check sets an arbitrary value if it wasn’t within the range instead of just assigning one of the bounds to the value. That caused me to split it into a test, within(), to handle this case and a setwithin() to handle the earlier cases.
Splitting it also let me do a minor optimization. The typical case is that being out of bounds is rather exceptional and it’d be nice to avoid doing a copy. Accordingly, setwithin() checks if the dest has the same address as the replacement value and avoids doing the assignment.
int within (const Type & lower, const Type & val, const Type & upper)
{
if (val < lower)
return -1;
if (upper < val)
return 1;
return 0;
}
template
int setwithin (const Type & lower, const Type & val, const Type & upper, Type & dest)
{
int res = within (lower, val, upper);
switch (res)
{
case -1:
if (&lower != &dest)
dest = lower;
break;
case 0:
if (&val != &dest)
dest = val;
break;
case 1:
if (&upper != &dest)
dest = upper;
break;
}
return res;
}
Switching keys in values in a map
Sunday, July 4th, 2010A functor that reverses a pair: first becomes second, second becomes first. Useful for switching from a map to another map (or multimap in this example) where the value becomes the key and the key the value.
std::map m;
std::multimap m2;
m["a"] = 0;
m["b"] = 1;
m["c"] = 0;
std::transform (m.begin(), m.end(), std::inserter (m2, m2.begin()),
pair_switch<std::map::value_type> ());
And the actual code:
template
struct pair_switch : public std::unary_function<
std::pair,
std::pair >
{
typedef std::pair argument_type;
typedef std::pair argument_type2;
typedef std::pair argument_type3;
typedef std::pair result_type;
result_type operator()(const argument_type3 &p) const
{
return result_type (p.second, p.first);
}
};
Xcode: notes
Sunday, November 29th, 2009To reset Xcode to the default settings:
$ defaults delete com.apple.Xcode
$ rm -rf ~/Library/Application\ Support/Xcode
First, I dislike having a lot of popup windows so I set the layout to “All-In-One” to keep most things within a single window:
And my usual indentation style:
I like having the files autosaved on build:
sqlite3 rocks
Friday, August 21st, 2009I’d been using the sqlite3 that came installed on Mac OS X but I ran into some portability issues — not every system has it installed. So I decided to bite the bullet and include it with my code.
It was trivial! I downloaded a zip with 3 files (sqlite3.c,sqlite3.h, and sqlite3ext.h). Added sqlite3.c to my list of sources and it just compiled! No configuration, no trickly flags, it just worked!
Getting the keys from a std::map
Thursday, May 21st, 2009So last week I wrote about initializing a std::map from two std::vectors. How about doing the reverse? How do I get a list of the keys or a list of the values into a vector?
So I wrote a functor, based on std::unary_function, that returns the pair.first and another that returns the pair.second:
include
include
/**
* A functor that returns the first in a pair
*/
template<typename PairType>
struct first: public std::unary_function<PairType, typename PairType::first_type>
{
typedef typename PairType::first_type result_type;
typedef PairType argument_type;
result_type operator()(argument_type &p) const
{
return p.first;
}
result_type operator()(const argument_type &p) const
{
return p.first;
}
};
/**
* A functor that returns the second in a pair
*/
template<typename PairType>
struct second: public std::unary_function<PairType, typename PairType::second_type>
{
typedef typename PairType::second_type result_type;
typedef PairType argument_type;
result_type operator()(argument_type &p) const
{
return p.second;
}
result_type operator()(const argument_type &p) const
{
return p.second;
}
};
The first() template functor (from above) is used as the functor that returns the key to the std::transform() alogrithm. Here is a little fragment code that uses first(). (The test code part of a larger CPPUNIT test suite):
void TestUtils::testFirst()
{
typedef std::map String2StringMap;
String2StringMap m;
m["a"] = "0";
m["z"] = "1";
m["x"] = "2";
std::vector<std::string> keys;
std::transform (m.begin(), m.end(),
std::back_inserter (keys),
first<String2StringMap::value_type>());
CPPUNIT_ASSERT_EQUAL (m.size(), keys.size());
CPPUNIT_ASSERT_EQUAL (std::string ("x"), keys[1]);
}
Functor for deleting objects
Wednesday, May 20th, 2009In a destructor for a class, I had a std::vector of pointers that I wanted to delete. I started to write the usual for(;;) loop and realized I do this often enough I should make it easy to use std::for_each().
Here’s the functor (based on std::unary_function):
#include
template<typename Type>
struct deleter: public std::unary_function<Type *, bool>
{
bool operator()(Type * ptr) const
{
delete ptr;
return true;
}
};
And here’s some sample code using it:
std::vector m_symbols;
// ...
std::for_each (m_symbols.begin(), m_symbols.end(), deleter());
I added a return of true because some other template code wasn’t happy about “return void” — supposedly something fixed in recent compilers.
A better output_iterator
Tuesday, May 19th, 2009I was using the std::stream_iterator, for example:
std::vector vals;
vals.push_back (12);
vals.push_back (22);
vals.push_back (5);
vals.push_back (30);
// The std::ostream_iterator appends the ","
std::ostringstream str3;
std::copy (vals.begin(), vals.end(), std::ostream_iterator<int> (str3, ","));
CPPUNIT_ASSERT_EQUAL (std::string ("12,22,5,30,"), str3.str());
It has the “,” after the last item.
So here’s an implementation that doesn’t append the seperator after the last one:
ifndef INCLUDED_OUTITER_H
define INCLUDED_OUTITER_H
include
/**
* A replacement for std::ostream_iterator that doesn't put the
* seperator after the last item.
*/
template >
class outiter : public std::iterator
{
public:
typedef CharType char_type;
typedef Traits traits_type;
typedef std::basic_ostream ostream_type;
/// Initialize from a stream
outiter (ostream_type &stream)
: m_stream (&stream),
m_string (0),
m_started (false)
{}
/// Copy constructor
outiter (const outiter ©)
: m_stream (copy.m_stream),
m_string (copy.m_string),
m_started (copy.m_started)
{}
/// Initialize from a stream and the seperator
outiter (ostream_type &stream, const CharType *str)
: m_stream (&stream),
m_string (str),
m_started (false)
{}
/// Assignment actually does the output
outiter &
operator=(const Type &value)
{
if (!m_started)
{
m_started = true;
}
else if (m_string)
{
(*m_stream) << m_string;
}
(*m_stream) << value;
return *this;
}
/// Just return a reference to this
outiter &
operator*()
{
return *this;
}
/// Just return a reference to this
outiter &
operator++()
{
return *this;
}
/// Just return a reference to this
outiter &
operator++(int)
{
return *this;
}
private:
/// The stream to write to
ostream_type * m_stream;
/// The seperator (may be NULL)
const char_type * m_string;
/// Flag to indicate if we've output anything
bool m_started;
};
endif /* INCLUDED_OUTITER_H */
And here’s the corresponding code to use it:
std::ostringstream str;
std::copy (vals.begin(), vals.end(), outiter (str, ","));
CPPUNIT_ASSERT_EQUAL (std::string ("12,22,5,30"), str.str());
Copying a std::vector into a std::map
Friday, May 8th, 2009I had two vector’s with the first being the keys and the second being the values. It took a couple tries before I got the STL working for me!
The first thing was to check if the std::map constructors had something useful. It certainly seems like taking two sets of iterators would be a great way to initialize a map. No such luck.
So how about one of the std algorithms to copy the keys and values into the map? std::copy seemed likely but it only takes a single sequence. A little more digging and std::transform. The second version of std::transform takes two sequences, an output iterator, and a binary function to convert the two values from the two sequences into something that can be inserted into the output iterator. Perfect.
So how to turn the two values into a pair suitable for std::map? The std::make_pair is exactly what is needed. The hard part is getting the syntax so you can pass it as a function: make_pair<std::string,int> in this example.
So the code finally looks like:
include
include
include
include
include
include
void test()
{
std::map m;
std::vector keys;
std::vector values;
std::transform (keys.begin(), keys.end(),
values.begin(),
std::inserter (m, m.begin()),
std::make_pair<std::string,int>);
}


