.Page.Metafunctions:
..XXXcat:Basics
..order:zzz010
..summary:Metafunctions are used for getting types and constants at compile time.

.Page.Metafunctions.description:
..contents
..image:metafunctions

..section:# Motivation

..text:
Generic algorithms usually have to know certain types that correspond to their arguments: An algorithm
on strings may need to know which type of characters are stored in the string, or what kind of iterator can
be used to browse it. SeqAn uses @Metafunction|Metafunctions@ (also known as "traits") for that purpose. 

..text:For example: Assuming that we define a @Class.String|string@ of @Spec.AminoAcid|amino acids@:
..code:String<AminoAcid> str = "ARN";
..text:Now lets define a function that exchanges the first two values in a string:
..code:
void exchangeFirstValues(String<AminoAcid> & str)
{
    if (length(str) < 2) return;
    AminoAcid temp = str[0];
    str[0] = str[1];
    str[1] = temp;
}
..text:Since this function only works for instances of $String<AminoAcid>$, we could try to make it more general by making a template out of it:
..code:
template <typename T>
void exchangeFirstValues(T & str)
{
    if (length(str) < 2) return;
    AminoAcid temp = str[0];
    str[0] = str[1];
    str[1] = temp;
}
..text:Now the function works for all sequence types $T$ that store $AminoAcid$ objects, 
but it will fail for other value types as soon as the variable $temp$ cannot store $str[0]$ anymore.
To overcome this problem, we must redefine $temp$ in a way that it can store a value of the correct type.
The question is: "Given a arbitrary type $T$, what is the value type of $T$?"
The metafunction @Metafunction.Value@ anwers this question: "The value type of $T$ is given by $Value<T>::Type$."
Hence, the final version of our function $exchangeFirstValues$ reads as follows:
..code:
template <typename T>
void exchangeFirstValues(T & str)
{
    if (length(str) < 2) return;
    typename Value<T>::Type temp = str[0];
    str[0] = str[1];
    str[1] = temp;
}
..text:
We can view $Value$ as a kind of "function" that takes $T$ as an argument (in angle brackets) and returns the required value type of $T$.
In fact, $Value$ is not implemented as a C++ function, but as a class template. 
This class template is specialized for each sequence type $T$ in a way that 
the $typedef Type$ provides the value type of $T$.
Unfortunately, the current C++ language standard does not allow to write simply "$Value<T> temp;$", so we must select the return value by appending "$::Type$".
The leading "$typename$" becomes necessary since $Value<T>::Type$ is a type that depends on a template parameter of the surrounding function template.


..section:# Type Metafunctions
..text:The metafunction @Metafunction.Value@ is a type metafunction, i.e. it is used to determine a type.
Type metafunctions have the form:
..code:typename TypeMetaFunc<T1, T2, ..., TN>::Type
..table:$TypeMetaFunc$|The name of the metafunction
..table:$T1$, $T2$, ..., $TN$|Arguments (types or constants)
..table:$Type$|The resulting type
..text:The keyword $typename$ must be stated if one of the arguments $T1$, $T2$, ..., $TN$ is or uses a template parameter.

..text:Example: The following piece of code uses the metafunction @Metafunction.Iterator@ to determine an iterator type for a @Class.String|string class@:
..code:
String<char> str = "I am a string";
Iterator<String<char> >::Type it = begin(str);
while (! atEnd(it, str)) 
{
    ::std::cout << *it;
    ++it;
}


..section:# Value Metafunctions
..text:Metafunctions can also be used to determine constant values at compile time. The general form of value metafunctions is:
..code:VALUE_META_FUNC<T1, T2, ..., TN>::VALUE
..table:$VALUE_META_FUNC$|The name of the metafunction
..table:$T1$, $T2$, ..., $TN$|Arguments (types or constants)
..table:$VALUE$|The resulting constant value

..text:Example:The following function prints the length of a fixed sized string using the value metafunction @Metafunction.LENGTH@:
..code:
template <typename T>
void printLenOfFixedSizeString(T const &)
{
    ::std::cout << LENGTH<T>::VALUE;
}

String<char, Array<100> > my_str;
printLenOfFixedSizeString(my_str);
..output:100

