#include <algorithm>
#include <cctype>
#include <string>
#include <iostream>

template <typename InputIterator, typename OutputIterator>
OutputIterator caesar_cipher(InputIterator src_begin, InputIterator src_end, OutputIterator dest_begin, int shift)
{
    const std::string ab("abcdefghijklmnopqrstuvwxyz"); // AlphaBet
    std::string rot_ab(ab); // ROTated AlphaBet

    shift %= static_cast<int> (ab.length()); // bring the shift within the length of the alphabet

    if (shift < 0)
        std::rotate(rot_ab.rbegin(), rot_ab.rbegin() - shift, rot_ab.rend());
    else
        std::rotate(rot_ab.begin(), rot_ab.begin() + shift, rot_ab.end());
        
    auto rotator = [ab, rot_ab](char c) -> char {
        if (std::isalpha(c))
        {
            if (std::isupper(c))
                return std::toupper(rot_ab.at(ab.find(std::tolower(c))));

            return rot_ab.at(ab.find(c));
        }

        return c;
    };

    return std::transform(src_begin, src_end, dest_begin, rotator);
}

int main() {
    std::string s = "Wkh Txlfn Eurzq Ira Mxpsv Ryhu Wkh Odcb Grj";

    caesar_cipher(s.begin(), s.end(), s.begin(), -3);
    std::cout << s << std::endl;
}