コンパイル時toupperとtolower

見たまんまですね。
文字列リテラル又はsprout::stringから処理を施したsprout::stringを生成します。

C++1yならdecltypeの部分は無くても動きますが、C++11対応のため。

#include <type_traits>
#include <sprout/string.hpp>
#include <sprout/index_tuple.hpp>

template<class T, std::size_t size, sprout::index_t... indexes>
constexpr auto toupper_impl(const T (&str)[size], sprout::index_tuple<indexes...>)
-> decltype(
            sprout::make_string(static_cast<char>('a' <= str[indexes] && str[indexes] <= 'z' ? str[indexes] - ('a' - 'A') : str[indexes])...)
            )
{
    return sprout::make_string(static_cast<char>('a' <= str[indexes] && str[indexes] <= 'z' ? str[indexes] - ('a' - 'A') : str[indexes])...);
}

template<class T, std::size_t size>
constexpr auto toupper(const T (&str)[size])
-> decltype(
            toupper_impl(str, typename sprout::index_range<0, size>::type())
            )

{
    return toupper_impl(str, typename sprout::index_range<0, size>::type());
}

template<std::size_t size, sprout::index_t... indexes>
constexpr auto toupper_impl(const sprout::string<size> str, sprout::index_tuple<indexes...>)
-> decltype(
            sprout::make_string(static_cast<char>('a' <= str[indexes] && str[indexes] <= 'z' ? str[indexes] - ('a' - 'A') : str[indexes])...)
            )
{
    return sprout::make_string(static_cast<char>('a' <= str[indexes] && str[indexes] <= 'z' ? str[indexes] - ('a' - 'A') : str[indexes])...);
}

template<std::size_t size>
constexpr auto toupper(const sprout::string<size> str)
-> decltype(
            toupper_impl(str, typename sprout::index_range<0, size>::type())
            )

{
    return toupper_impl(str, typename sprout::index_range<0, size>::type());
}


template<class T, std::size_t size, sprout::index_t... indexes>
constexpr auto tolower_impl(const T (&str)[size], sprout::index_tuple<indexes...>)
-> decltype(
            sprout::make_string(static_cast<char>('A' <= str[indexes] && str[indexes] <= 'Z' ? str[indexes] + ('a' - 'A') : str[indexes])...)
            )
{
    return sprout::make_string(static_cast<char>('A' <= str[indexes] && str[indexes] <= 'Z' ? str[indexes] + ('a' - 'A') : str[indexes])...);
}

template<class T, std::size_t size>
constexpr auto tolower(const T (&str)[size])
-> decltype(
            tolower_impl(str, typename sprout::index_range<0, size>::type())
            )

{
    return tolower_impl(str, typename sprout::index_range<0, size>::type());
}

template<std::size_t size, sprout::index_t... indexes>
constexpr auto tolower_impl(const sprout::string<size> str, sprout::index_tuple<indexes...>)
-> decltype(
            sprout::make_string(static_cast<char>('A' <= str[indexes] && str[indexes] <= 'Z' ? str[indexes] + ('a' - 'A') : str[indexes])...)
            )
{
    return sprout::make_string(static_cast<char>('A' <= str[indexes] && str[indexes] <= 'Z' ? str[indexes] + ('a' - 'A') : str[indexes])...);
}

template<std::size_t size>
constexpr auto tolower(const sprout::string<size> str)
-> decltype(
            tolower_impl(str, typename sprout::index_range<0, size>::type())
            )
{
    return tolower_impl(str, typename sprout::index_range<0, size>::type());
}


int main()
{
    constexpr auto upp1 = toupper("sprout");
    constexpr auto low1 = tolower("SPROUT");
    constexpr auto upp2 = toupper(low1);
    constexpr auto low2 = tolower(upp1);
    
    static_assert(upp1 == "SPROUT", "");
    static_assert(low1 == "sprout", "");
    static_assert(upp2 == "SPROUT", "");
    static_assert(low2 == "sprout", "");
}