как заполнить вектор аргументами шаблонной функции и каждому аргументу присвоить новое значение чтобы были отсортированны

template<typename... Ts>
void asort(Ts&... ts)
{
    vector<Ts> arr{ (ts...,) }; // ?? как заполнить вектор аргументами ts
    std::sort(begin(arr), end(arr));
    for (size_t i = 0; i < arr.size(); i++)
    {
        ts[i] = arr[i]; // ?? каждой переменной пакета ts присвоить значение вектора
    }
}

int main()
{  

    int a = 0, b = 99, c = 23;
    asort(a, b, c); // сортируем переменные
    cout << a << '\t' << b << '\t' << c << endl;
}

Я делаю функцию сортировки переменных. Написал псевдокод. Помогите с распаковкой аргументов.

Реализовал так:

template<typename T, typename... Ts>
void mysort(T& t, Ts&... ts)
{
    vector<T> vars;
    vars.push_back(t);
    (vars.push_back(ts), ...);
    sort(vars.begin(), vars.end());
    vector<T*> vars2;
    vars2.push_back(&t);
    (vars2.push_back(&ts), ...);
    for (size_t i = 0; i < vars.size(); i++)
    {
        *vars2[i] = vars[i];
    }
}

int main()
{  
    string a = "x", b = "e", c = "a";
   
    cout << a << ' ' << b << ' ' << c << endl;
    mysort(a, b, c);
    cout << a << ' ' << b << ' ' << c << endl;
}

Ответы (3 шт):

Автор решения: AR Hovsepyan

Поместить объекты разных типов в вектор _ не получится. Если нужно поместить значения аргументов, то вам нужна функция с переменным количеством аргументов одного типа. Эти аргументы будут последовательно расположены в коробке функции, поэтому имея адрес первого аргумента, можно обращаться ко всем остальным, если будет какой то маркер конца. Например, в аргумент передавая количество аргументов или при вызове функции, передать нулевой указатель(если аргументы являются указателями). Аргументами могут быть указатели, но со ссылками не получится, потому что ссылки не занимают память в стеке, и не будет возможность обращаться ко всем переданным объектам. Поэтому лучше возвращать из функции контейнер, а потом использовать по усмотрению:

template<typename Ts>
std::vector<Ts> asort(int n, Ts ts,...)
{
    Ts* p = &ts;
    std::vector<Ts> arr; // ?? как заполнить вектор аргументами ts
    while (n--) {
        arr.push_back(*p);
        ++p;
    }
    std::sort(arr.begin(), arr.end());
    return arr;
}

В качестве примера присвоим значение последнего аргумента:

//первый аргумент _ это количество аргументов    
int a = asort(3, 4, 5, 6).back(); 

Можно также написать функцию без указания количества аргументов. Тогда нужно воспользоваться вариантом надежней _ услугами va_list, va_start

→ Ссылка
Автор решения: user489495

Поместить значения в вектор не проблема (если они одного типа, что тоже можно проверить в compile time)

std::vector arr{ {ts...} };

Проблема потом присвоить аргументам соответствующие значения вектора. Для этого надо из вектора сделать std::tuple и сделать zip тапла std::tie(ts...) и этого тапла с операцией = или использовать = прямо на таплах. Либо costexpr for с std::get<I>(tup_1) = std::get<I>(tup_2). Оба способа требуют много бойлерплейта. Гораздо проще изменить дизайн функции и не использовать входные аргументы, как выходные параметры, а просто возвращать отсортированный вектор. Также можно использовать std::array, раз количество элементов заранее известно.

→ Ссылка
Автор решения: ТарасПрогер
#include <iostream>
#include <cassert>
#include <tuple>
using namespace std;

template <size_t I>
struct visit_impl
{
    template <typename T, typename F>
    static auto visit(T& tup, size_t idx, F fun)
    {
        if (idx == I - 1)
            return fun(&std::get<I - 1>(tup));
        else 
        {
            visit_impl<I - 1>::visit(tup, idx, fun);
        };
    }
};

template <>
struct visit_impl<0>
{
    template <typename T, typename F>
    static void visit(T& tup, size_t idx, F fun) { assert(false); }
};



template <typename F, typename... Ts>
auto visit_at(std::tuple<Ts...>& tup, size_t idx, F fun)
{
    return visit_impl<sizeof...(Ts)>::visit(tup, idx, fun);
}


template<typename pred = std::greater<>, typename... Ts>
void sort(Ts&... ts)
{
    tuple<Ts...> tuple{ts...};
    auto get_val = [](auto* val) { return val; };


    for (int startIndex = 0; startIndex < sizeof...(Ts) - 1; ++startIndex)
    {
        int smallestIndex = startIndex;

        for (int currentIndex = startIndex + 1; currentIndex < sizeof...(Ts) - 1; ++currentIndex)
        {
            if (pred{}(*visit_at(tuple, currentIndex, get_val), *visit_at(tuple, smallestIndex, get_val) ))
                smallestIndex = currentIndex;
        }
        std::swap(*visit_at(tuple, startIndex, get_val), *visit_at(tuple, smallestIndex, get_val));
    }
    

    size_t pos = 0;


    (void)initializer_list {
        (ts = *visit_at(tuple, pos, get_val), ++pos)...
    };

 
}

int main()
{ 
    int a = -12, b = 66, c = -1;
    sort(a, b, c);
    cout << a   << ' ' << b << ' '<< c;   
}

На основе кортежей. Можно заменить на другую сортировку

→ Ссылка