måndag 20 april 2009

Template specialization sucks

A wise man (Herb Sutter) once said that you should avoid function template specialization. After what I experienced today, I can only agree.

As we know, the compiler has to do a lot of background work when you declare templates. Unfortunately, all compilers handles templates a little bit differently. Watch this code taken from stackoverflow which was supplies as an answer to me regarding a template problem:

template <typename X> struct Test {}; 
struct X
{
template <typename T>
static void f( Test<T> );
};

// template definition:
template <typename T>
void X::f( Test<T> ) {
std
::cout << "generic" << std::endl;
}
template <>
void X::f<void>( Test<void> ) {
std
::cout << "specific" << std::endl;
}

int main()
{
Test<int> ti;
Test<void> tv;
X
::f( ti ); // prints 'generic'
X
::f( tv ); // prints 'specific'
}
We have here a simple template specialization for the void type. This will compile and run fine under any compiler.

However, often we use multiple static libs. If we instead put the template specification in another lib and linked it to our main application where main() resides, it would still work fine. On some compilers.

It turns out that MSVC can handle this without any problems, while gcc will generate a "multiple definitions" error for f(). Obviously, this has something to do with how the function tables are constructed during linking, but I have not explored it more deeply than that.

As it happens, there's a fix for this problem. Declaring the speccialization as inline will remove the compiler error. With inline , a copy of the function body is inserted everywhere the function is called. No normal calls (including a jump, stack things etc) are done.

However, the point here is that templates in general and template specialization in particular, are advanced concepts that should only be used with uttermost care in your code. There is no way to underestimate the benefits of having code that compiles on all standard compilers. Therefore, follow Sutter's advice and use template specialization only when you really have to.

söndag 19 april 2009

Från hanterad kod till C++, del 3

Detta är del 3 i inläggsserien om att gå från .NET/Java till C++. Förra delen handlade om olika typer av keywords och mekanismer i C++ som är krångliga. Denna del ska handla om Boost, det bästa tillägget till Standard C++.

Boost
Många lär sig tidigt att använda Standard Template Library, STL, till C++. STL inkluderar många klasser man använder dagligen t ex std::vector, std::map och std::string, för att nämna de vanligaste. STL är helt okej, men det finns en ramverk som delvis ersätter och delvis kompletterar STL, nämligen Boost.

Boost underhålls av några mycket tunga namn från C++ världen, många som även sitter med i C++ standardkommite. Detta har resulterat i att flera Boostklasser nu är en del av Standard C++.

Jag tycker att Boost är det absolut bästa komplementet till C++, och många av Boost klasser som ersätter STL är betydligt bättre än originalet. Boost är också mycket trevligt att använda; den mesta koden ligger direkt i header-filerna så man behöver ofta inte ens lib-filerna. Självklart är också hela Boost plattformsoberoende.

För att visa hur trevliga Boostbiliboteken är presenterar jag några klasser som vi ofta använder på jobbet.


FOREACH
Många språk (t ex C# och Perl) har en inbyggd foreach funktionalitet för att iterera igenom listor. I C++ finns det flera olika försök till att implementera detta, men Boost har lyckats bäst. Syntaxen är väldigt smidig och mycket lik den i C#:

#include <boost/foreach.hpp>

// skriver ut "2" på skärmen

void main()
{
std::vector<int> vec;
vec.push_back(2);

BOOST_FOREACH(int i, vec)
{
std::cout << i << std::endl;
}
}

Tuple
Väldigt ofta vill man på ett enkelt sätt associera två eller fler objekt med varann. T ex kanske man bara snabbt vill få ut en x,y punkt ur en funktion, och man orkar inte skapa en klass eller struct bara för att uppnå detta. Då är tuples perfekta. Följande exempel visar hur man skapar tuples och hämtar värdena i en tuple.

#include <boost/tuple/tuple.hpp>


boost::tuples::tuple<std::string, int> getPerson()
{
boost::tuples::tuple<std::string, int> point_tuple("Per", 20);
return point_tuple;
}

void main()
{
boost::tuples::tuple<std::string, int> pers = getPerson();

std::string name = boost::tuples::get<0>(pers);
int age = boost::tuples::get<1>(pers);
}

Om man inte vill ange typerna då man skapar en tuple kan man låta Boost gissa dem genom att använda make_tuple (exemplet taget från boost.org):


tuple<int, int, double> add_multiply_divide(int a, int b)
{
return make_tuple(a+b, a*b, double(a)/double(b));
}

Det finns massor av mer funktionalitet kring tuple, som t ex jämförelser och input/output. tuples lämpar sig bra tillsammans med en typedef eller två, då uttrycken tenderar att bli långa.


Any
Man vill ofta ha ett sätt att lagra helt olika, orelaterade typer i en lista eller annan behållare. Det kan röra sig om inställningar, kolumner från en databas, funktionspekare eller vad som helst. Genom åren har man använt sig av flera olika alternativ för att göra detta. Ett sätt är att kasta allt till void*, vilket är ett väldigt osäkert och fult sätt. Man kan även använda sig av union eller någon form av arvstruktur med en generell basklass.

Det överlägset bästa sättet är att använda sig av boost::any. boost::any lagrar på ett typsäkert sätt vilken typ som helst. Se följande exempel för deklarationen:

#include <boost/any.hpp>

void main()
{
std::vector<boost::any> anyValues;

int i = 40;
std::string s = "hej";

boost::any anyInt = i;
boost::any anyString = s;

anyValues.push_back(anyInt);
anyValues.push_back(anyString);
}
För att avgöra vilken typ en boost::any har använder man metoden type():

BOOST_FOREACH (boost::any a, anyValues)
{
if (a.type() == typeid(int))
int i = boost::any_cast<int>(a);
else if (a.type() == typeid(std::string))
std::string s = boost::any_cast<std::string>(a);
}

Smart pointers

Genom mekanismen new/delete tvingas man som programmerare att komma ihåg att avallokera minne vid rätt tidpunkt i C++. Detta är något helt främmande för oss som använder hanterade språk där Garbage Collector automatisk avallokerar minne som inte längre används.

Sån tur är behöver man inte tänka på sådant i C++ längre; det finns flera implementationer av s.k smarta pekare som ser till att minnet frigörs automatiskt. Den vanligaste är boost::shared_ptr. Den använder referensräkning för att hålla reda på när ett objekt kan deallokeras.

Genom att alltid göra som i exemplet nedan då du tänkte skriva "new" slipper du helt minnesläckor associerade med dynamisk minnerallokering:

#include <boost/shared_ptr.hpp>

class MyClass
{
public:
void memberFunction() {;};
};

typedef boost::shared_ptr<MyClass> MyClassPtr; // bra med typedef då det tenderar bli långa rader


void main()
{
MyClassPtr myclass(new MyClass()); // istället för bara "new"

myclass.get()->memberFunction(); // get() returnerar en vanlig pekare till klassen så medlemmar kan anropas

} // här kommer myclass automatiskt att raderas

Om man vill skapa en smart pointer till en array bör man använda shared_array. shared_array är egentligen identisk med shared_ptr, men den använder sig av new[] och delete[], som sig bör för pekare till arrayer.

En sak man måste tänkta på är att aldrig stoppa en smart-pointer inuti en annan smart-pointer. Detta kommer att resultera i att boost försöker deallokera objektet två gånger, vilket ger ett runtime-fel. Man ska också komma ihåg att det inte bara är boost som implementerar smart-pointers; därför måste man se till att det man stoppar in i en boost::shared_ptr inte redan är "smart-pointifierad" sedan tidigare om man använder något externt API.


Thread

Boost definierar en plattformsoberoende trådmekanism, boost::thread. Det trevliga är just att den är plattformsoberoende; man slipper använda Windows thread, pthreads eller något GUI-specifikt trådbibliotek (MFC, GTK och QT har alla egna trådklasser).

Självklart implementeras boost::thread med antingen Windows threads eller pthreads beroende på system, men detta är inget vi behöver bry oss om. Enklaste tänkbara exemplet:

#include <boost/thread/thread.hpp>

void func()
{
}


void main()
{
boost::thread thrd(&func);
}

Ovan startar omedelbart en tråd som börjar exekvera func().
Ibland vill vi skicka in ett argument till funktionen som ska köras. Innan boost 1.35 var det lite krångligare, men nu kan man helt enkelt skriva:

#include <boost/thread/thread.hpp>

void func(int inArg)
{
// kallas med inArg = 243
}

void main()
{
boost::thread thrd(func, 243);
}
Det är inga problem att knyta en medlemsfunktion till en tråd:

#include <boost/thread/thread.hpp>

class MyClass
{
public:
void fun(int inarg)
{
// ...

}
void runThread()
{
boost::thread(&MyClass::fun, this, 243);
}
int m_i;
};
Förutom detta finns en uppsjö med olika mutex att använda för att trådsäkra och synkronisera din kod. Se boost dokumentation.


lexical_cast

Ofta vill man kunna röra sig mellan siffror och strängar på ett smidigt sätt. Tex vill man kanske översätta

std::string = "3.5"

till en double eller int vid senare tillfälle. Det finns lite olika sätt att göra detta. Man kan använda atoi, atof, sprintf osv osv. Boost definierar istället en enda cast, lexical_cast, för allt sådant. Koden nedan är självförklarande.

#include <boost/lexical_cast.hpp>

void main()
{
std::string s = "3.5";

double d = boost::lexical_cast<double> (s);
int i = boost::lexical_cast<int> (s);
std::string s2 = boost::lexical_cast<std::string> (i);
}

function och bind

boost::function och boost::bind är två fantastiska verktyg för att (bland annat) skapa och använda funktionspekare och att ändra funktioners aritet. Koncepten är hyfsat avancerade och förtjänar ett helt eget inlägg. Just nu kan jag bara nämna att detta är vad du ska använda då du behöver funktionspekare eller unära funktioner i C++.

söndag 12 april 2009

What are you doing to my PS3, Sony?

Just felt the urge to rant for a minute. After upgrading to the newest PS3 firmware (2.70), I, toghether with many others, found I can no longer stream files from my mediaserver. All files turn up as "unsupported data", and apparently, there is no fix, 'specially since you can't downgrade the damn thing!

I use LinkSys NSLU NAS running Mediatomb as a mediaserver for the PS3, among other things, and it has so far served me flawlessly. Let me put in a good word for the NSLU while I'm at it.

This affordable little piece is a real wonder if you use it to run Linux. I use it for a development MySQL Server, SVN, media streaming (or I did until now), Bittorrent client, and as a general fileserver. The NSLU package repository is huge; you can use for for lots of other stuff as well. For about $100, this is not bad.

Well, enough about that. I hope Sony either fixes this in the next release or provides a downgrade capatibility.

Update:
It seems the 2.70 firmware re-introduced an old bug in the DLNA protocol regarding divx playback. A fix in Mediatomb for this can be found here.

torsdag 2 april 2009

Script to add svn version to your code

In the project I'm currently in, I found it very convenient to include the SVN version number of the release in the application's GUI. If a customer has a problem, we then knows for sure what version they are using, and we don't have to rely on our sometimes shaky release management being correct.

A bash script puts the current SVN version number in a #define in a C++ header file, which is then included in the project and displayed in the 'About box', next to the official version number.

I have included the script below that extracts the version number from the top level .svn/entries database in the project, and puts it in a file VERSION_CPP_FILEPATH that contains the row "#define SVN_VERSION = "

This bash script is then executed as a pre-build action in our IDE.

#/!bin/sh
VERSION_CPP_FILEPATH=../inc/version.hpp
SVN_ENTRIES_PATH=../../.svn/entries

VERS=`cat $SVN_ENTRIES_PATH | grep dir -A 2 | sed -n '2p'`
sed "s/#define SVN_VERSION .*/#define SVN_VERSION $VERS/g" $VERSION_CPP_FILEPATH > tmp.hpp
rm $VERSION_CPP_FILEPATH
mv tmp.hpp $VERSION_CPP_FILEPATH

onsdag 1 april 2009

Från hanterad kod till C++, del 2

Detta är del två i inläggsserien "Från hanterad kod till C++". Del 1 handlade främst om pekare och keywordet new, två ganska jobbiga C/C++ begrepp. Denna del handlar om lite olika mekanismer i C++ som jag tycker kan vara förvirrande i början. En exempel är keyword som får helt olika betydelse beroende på i vilket sammanhang de används. Andra exempel är mekanismer som syntaktiskt är lika andra språk men som i C++ fungerar på ett speciellt sätt.

Casting
C++ har ärvt mycket funktionalitet från C som man inte bör använda. En sådan grej är typecasting. Följande kod kompilerar fint i en C++ kompilator:

void func(DerivedClass *d)
{
BaseClass *b;
b = (BaseClass*) d;
}

Detta ser även identiskt ut med Java/.NETs typecasting. Hursomhelst avråds man från att typecasta på detta sätt i C++, i varje fall för klasser och pekare. För grundtyper tycker jag dock att ovanstående s.k C-style casting är helt okej:


double
d = 3.3;

int i = (int) d;

Men för klasser och pekare, som sagt, bör man använda de i C++ fördefinierade operatorerna:

static_cast (expression)
dynamic_cast (expression)
const_cast (expression)
reinterpret_cast (expression)

De två man använder ofta av dessa är static_cast och dynamic_cast. Dessa finns mycket bra beskrivna på MSDN men jag ska presentera dem i sin korthet.

static_cast

static_cast är den "hårdaste" typen av casting; du tvingar kompilatorn att försöka casta mellan de två typerna, utan att någon runtime-kontroll görs om det går. Detta kan vara bra t ex vid casting nedåt i ett klassträd, då du är säkert på att klassen du vill casta även är av typen du castar till. Till exempel:

class B {};
class D : public B {};

void f(B* pb)
{
D* pd2 = static_cast(pb); // du vet att pb är en tidigare nedåt castad instans av D
}

Om du i exemplet ovan skulle råka ha fel (B är inte en istans av D) kan du få ett allvarligt fel, som t ex access violation.

dynamic_cast
dynamic_cast, vilket kanske är det vanligaste sättet att casta i C++, är mer säkert än static_cast. Vid en dymanic_cast sker en runtime-kontroll av att typerna stämmer, och även kompilatorn skulle klaga om man i exemplet ovan bytte ut static_cast mot dynamic_cast. dynamic_cast fungerar dock bara på pekare och referenser.

const
Ett exempel på ett fult keyword i C++ är const, då det får helt olika betydelser beroende på hur det används. Här är fem exempel:

MyClass
{
static const int myConst = 30; // exempel 1

const char* funcOne(int arg); // exempel 2

int funcTwo(const int arg); // exempel 3

int funcThree(int arg) const; // exempel 4

int funcFour(const BigClass &arg); // exempel 5

};

Första exemplet är enkelt, här deklarerar vi en vanlig konstant precis som i Java/.NET.

I exempel 2 används const för att garantera att returtypen är konstant. Om vi försöker ändra den returnerade char* så kommer vi att generera ett kompileringsfel, vilket är praktiskt just då man returnerar pekare och arrayer som man inte kan ändra på hur man vill.

I exempel 3 säger vi till kompilatorn att arg inte får ändras inne i funktionen (detta används oftast för pekare och referenser, som vi annars skulle kunna påverka inne i funktionen)

I exempel 4 säger vi att funktionen i sig aldrig kommer att ändra på någon medlem i MyClass. Detta kan vara bra för att försäkra sig om att ett funktionsanrop enbart är av ”get”-typ. Om vi försöker ändra på medlemar i klassen kommer kompilatorn att klaga.

Exempel 5 är likt exempel 2, men anledningen att const används här är av ett annat skäl. &-tecknet används här för att slippa att BigClass copy-constructor kallas (vilket ju inte sker då man skickar in en referens i funktionen). Programmeraren vill samtidigt förtydliga till de som ska använda funktionen att &-tecknet inte alls betyder att funktionen kommer att ändra arg, och därav const keywordet.

Templates
Motsvarigheten till generics i Java/.NET heter templates i C++ (eller tvärtom egentligen, då C++ var före). Det handlar alltså om att man kan skicka in en vid kompileringstid okänd typ som argument till en funktion eller som medlemsvariabel i en klass. I Java/.NET finns ju också grundtypen object, med vilken nästan samma sak kan uppnås. Dock så rekommenderas man att använda generics då man kan. I C++ finns inte object, så här måste man använda templates.

I Java/.NET används generics nästan uteslutande för listor av olika slag, men i C++ kan man se templates användas lite friskare, och de kan i vissa specifika tillämpningar verkligen bidra till snygg kod. Jag ska inte brodera ut för mycket i detta ämne, då mekanismen är väldigt lik den i Java/.NET. Det som dock kan nämnas är att C++ igen har förvirrat saker och ting genom att man kan deklarera templates på flera olika sätt, med precis samma betydelse. Till exempel är det ingen skillnad på de två följande deklarationerna:

template <class T> func(T arg);
template <typename T> func(T arg);
Som sagt kan templates användas både för enskilda funktioner (som ovan), eller för en hel klass. Man kan även definiera flera template-typer (här nedan för en hel klass):
template <class T, class U>
class MyClass
{
T member1;
U member2;
};

Det man ska tänka på med templates är att även om de syntaktiskt är mycket enkla, så gör kompilatorn en mängd saker bakom kulisserna för att det ska fungera. Detta kan ibland få oväntade effekter för dig som programmerare. Ett exempel är att function templates måste definieras i include-filen (och inte bara deklareras där, alltså) för att du ska kunna kalla funktionen från en annan fil. Detta har att göra med hur kompilatorn "gissar" vilka typer som funktionen ska förvänta sig.

copy constructor
Som jag nämnde i del 1 så används en implicit copy-constructor för att kopiera typer då argument ska slussas in i funktioner och ut som returvärden, samt vid tilldelningar. Undantaget är om man skickar pekare eller referenser. Detta är som sagt förvirrande för oss från Java/.NET då vi är vana vid att man alltid automatiskt skickar referensen till en klass, vad man än gör. Hursomhelst är det så det fungerar i C++, och det är bara att vänja sig.

Det finns möjlighet för en själv att definiera en copy-constructor till ens klass, vilken liknar den vanliga konstruktorn i utseende. Varför vill man göra detta? Svaret är att på vissa klasser duger inte den implicita copy-constructorn. Detta är fallet om en klass innehåller pekare till dynamiskt allokerat minne, alltså då keywordet new har använts i klassen. Vi måste då skriva en egen copy-constructor. Se följande exempel snott från www.codesource.net:

class B // Med copy constructor
{
private:
char *name;

public:
B()
{
name = new char[20];
}

~B()
{
delete name[];
}

// Copy constructor
B(const B &b)
{
name = new char[20];
strcpy(name, b.name);
}
};
name är en dynamiskt allokerad variabel, kommer vi att behöva den explicita konstruktorn för att kopiering av klassen ska utföras korrekt.

Slutsats
Detta var ett litet urval på egenheter med C++. Nästa inlägg kommer att handla om mitt favorittillägg till standard C++, nämligen Boost!