Signature Description
enum class shift_policy : unsigned char  {
    down = 1, // Shift/rotate the content of all columns down, keep index unchanged
    up = 2,   // Shift/rotate the content of all columns up, keep index unchanged
}; 
This policy is relative to a tabular data structure
There is no right or left shift (like Pandas), because columns in DataFrame have no ordering. They can only be accessed by name

Signature Description Parameters
template<typename ... Ts>
void
self_shift(size_type periods, shift_policy sp);
It shifts all the columns in self up or down based on shift_policy. Values that are shifted will be assigned to NaN. The index column remains unchanged. If user shifts with periods that is larger than the column length, all values in that column become NaN. Ts: The list of types for all columns. A type should be specified only once.
periods: Number of periods to shift
shift_policy: Specifies the direction (i.e. up/down) to shift
template<typename ... Ts>
StdDataFrame<I>
shift(size_type periods, shift_policy sp);
It is exactly the same as self_shift, but it leaves self unchanged and returns a new DataFrame with columns shifted.
static void test_shifting_up_down()  {

    std::cout << "\nTesting Shifting Up/Down ..." << std::endl;

    std::vector<unsigned long>  idx =
        { 123450, 123451, 123452, 123453, 123454, 123455, 123456, 123457, 123458, 123459, 123460, 123461, 123462, 123466 };
    std::vector<double>         d1 = { 15, 16, 15, 18, 19, 16, 21, 0.34, 1.56, 0.34, 2.3, 0.34, 19.0 };
    std::vector<int>            i1 = { 22, 23, 24, 25, 99 };
    std::vector<std::string>    s1 =
        { "qqqq", "wwww", "eeee", "rrrr", "tttt", "yyyy", "uuuu", "iiii", "oooo", "pppp", "2222", "aaaa", "dddd", "ffff" };
    MyDataFrame                 df;

    df.load_data(std::move(idx),
                 std::make_pair("dbl_col", d1),
                 std::make_pair("int_col", i1),
                 std::make_pair("str_col", s1));

    std::cout << "Original DF:" << std::endl;
    df.write<std::ostream, double, int, std::string>(std::cout);

    auto    sudf = df.shift<double, int, std::string>(3, shift_policy::up);

    std::cout << "Shifted Up DF:" << std::endl;
    sudf.write<std::ostream, double, int, std::string>(std::cout);

    auto    sddf = df.shift<double, int, std::string>(3, shift_policy::down);

    std::cout << "Shifted Down DF:" << std::endl;
    sddf.write<std::ostream, double, int, std::string>(std::cout);
}