27 February 2009

More frustration (Vim) resolved

Ugh, I spent the entire morning trying to fix a problem with Vim. I remember at one point getting frustrated that it refused to handle indentations of comments (which start with the hash or pound sign, #) correctly. The solution I got was to use someone else's indent file. Well, that indent file doesn't handle formatting lists extended over more than one line. But when I went back to the original, which worked for that, it couldn't handle the comments. I spent probably three hours searching for a solution, looking through $VIM/runtime/ trying to find out what the differences were between the different indent files. Furthermore, although the 'sh' file type displayed this behavior, the 'perl' file type did not!

Well, the long story was made short when I realized that the reason it forced all lines with a '#' to the beginning: it thought they were C preprocessor directives, which belong in column 1. I had unknowingly set an option, smartindent, which caused this behavior. Somehow, and I still haven't figured this out, the options in the Perl file mitigated that behavior.

Moral of this story: avoid setting options in vim that you aren't REALLY sure you understand. And with vim, this probably means you won't be setting many.

Template specialization for std::swap

One of the algorithms in C++'s STL is swap, a templated function which takes two arguments of the same class and switches them. By default, it creates a new object and performs two copies, but for STL containers (such as std::list, which I was using) it has its own template specialization to only copy their internal pointers and not any actual data. This makes, by default, std::swap way more efficient on an STL container than everything else.

I have a class Census inside a namespace iMc, and it has-a std::list to store a bunch of particles. I'd like to call std::swap(iMc::Census& a, iMc::Census& b) but not copy all the particles inside the list. The solution was obvious and allowed: create a new specialization for my own class that calls  std::swap on the std::list :
namespace std {
template<>
inline void swap<iMc::Census>(iMc::Census& a, iMc::Census& b)
{
std::swap(a._particles, b._particles);
}
} // end namespace std

Well, because the _particles list was private, I had to make this function a friend of iMc::Census. Easy, right? Wrong. It turns out everything on the internet; that talks about templated friend functions is a lie! No matter what I did, I received a bunch of weird errors.
namespace iMc {
class Census {
private:
template<typename T> friend void std::swap(T& a, T& b);
...
};
}
gives
build/imclib/Census.hpp:64: error: 'void std::swap(iMc::Census&, iMc::Census&)' should have been declared inside 'std'

and
friend template<> void std::swap<iMc::Census>(iMc::Census& a, iMc::Census& b);
gives
build/imclib/Census.hpp:64: error: expected unqualified-id before 'template'


Well, it turns out that the correct answer is to have
namespace iMc {
class Census {
private:
template<typename T> friend void std::swap(T& a, T& b);
...
};
}
Who would have guessed? I even checked Stroustroup's reference book, and it didn't look like it had syntax for templated friend functions in there. Hopefully no one else has to fool around and waste an hour of their time trying to do this.

18 February 2009

CC license

I'm LaTeXing my class notes, and I plan on distributing them in some sense. Here's the Creative Commons license in LaTeX that I came up with (which puts CC in a circle and uses the hyperref package to hyperlink it):
\newcommand{\cclicense}{%
\smash{\raisebox{-0.45ex}{%
\setlength{\unitlength}{1em}%
\begin{picture}(1,1)%
\put(0.5,0.5){\circle{1}}
\put(0.5,0.5){\hbox to 0pt{%
\hss\raisebox{-.45ex}{\tiny\textsf{CC}}\hss}}%
\end{picture}%
}}%
\hskip -1em%
\href{http://creativecommons.org/licenses/by-sa/3.0/}%
{\ \hskip 1em \textsf{BY-SA}}%
}
Update: thanks are due to Mike for pointing out my use of an externally defined term, which I thought was in base/latex.ltx but was actually defined elsewhere.

05 February 2009

MCNP syntax highlighting in vim

This syntax highlighter for MCNP in VIM is due to Giacomo Grasso. The file on his page is inaccessible other than through the white paper, so I have taken the liberty of extracting it and putting into a file available for download. Put it inside the ~/.vim/syntax folder.

There's no easy sure-fire way of detecting an MCNP input file, but if you create a file at ~/.vim/scripts.vim with the contents

if did_filetype() " filetype already set..
  finish  " ..don't do these checks
endif
if getline(2) =~ '^C.*\<mcnp\>\c'
  setfiletype imcnp
endif

it will load the MCNP syntax coloring if the second line of your input deck is a comment (the first letter of the line is a 'c') with the word MCNP in it somewhere.