Динамически создаваемый список аргументов, передаваемых в функцию Variadic

0

Я тестировал вариационные функции, надеясь, что я могу использовать его для решения проблемы, в которой мне нужно создать объект, содержащий произвольное количество аргументов. Он действительно работает отлично, но аргументы, переданные функции createObject, должны быть динамическими. В приведенном ниже примере только два аргумента передаются конструктору, но в конечной программе число и порядок, в которых передаются аргументы, должны быть произвольными (аргументы всегда имеют тип Param хотя).

Кажется, я не могу найти способ сделать это. Любая помощь, идеи и т.д. Были бы весьма признательны.

PS: Я нашел пару подобных вопросов в Stackoverflow, но они старые и не дают никакого приемлемого ответа.

struct Vec3f { float x, y, z; };
struct Vec2f { float x, y; };

template<class T>
struct Param
{
    static const std::size_t size = sizeof(T);
    Param(const std::string &n) : name(n) {}
    std::string name;
};

typedef Param<Vec3f> ParamFloat3;
typedef Param<Vec2f> ParamFloat2;

void parseParameters(std::size_t &stride) {}

template<class T, typename ... Types>
void parseParameters(std::size_t &stride, const Param<T> &first, Types ... args)
{
    stride += first.size;
    parseParameters(stride, args ...);
}

template<class T, typename ... Types>
void createObject(const Param<T> &first, Types ... args)
{
    std::size_t stride = 0;
    parseParameters(stride, first, args...);
}

int main(int argc, char **argv)
{
    ParamFloat3 test1("T1");
    ParamFloat2 test2("T2");
    createObject(test1, test2); // would like to make this dynamic
    return 0;
}
  • 0
    Что вы подразумеваете под "аргументами, передаваемыми в функцию createObject , должны быть динамическими"? Что значит «динамический» здесь?
Теги:
c++11

2 ответа

0
Лучший ответ

Все виды программирования шаблонов (включая вариационные шаблоны) разрешаются во время компиляции. Вам нужно будет передать контейнер (например, std::vector) в ваши функции.

Edit: Если вам нужно передавать параметры разных типов (Param<Vec3f> и Param<Vec2f> на самом деле Param<Vec2f> отличаются друг от друга, несмотря на то, что они поступают из одного и того же шаблона), вам нужно будет полагаться на полиморфизм. Дайте всем параметрам один и тот же базовый класс и используйте виртуальные функции или dynamic_cast для восстановления правильного поведения.

Самый безопасный способ добиться этого (и избегать обрезки объектов) - использовать std::vector<std::unique_ptr<Param>> где Param - ваш базовый класс.

  • 0
    Итак, учитывая, что ParamFloat2 и ParamFloat3 имеют разные типы, мне нужно сделать что-то вроде этого вектора <Param>, в котором ParamFloat2 и 3 на самом деле будут наследоваться от родительского класса Param? Старый добрый путь? Это нормально, просто хотел посмотреть, есть ли новый способ сделать это с новыми функциями из C ++ 11.
  • 0
    @ user18490 C ++ не имеет разнородных контейнерных средств, поэтому: да. Имейте в виду, что типы C ++ как первоклассные сущности полностью исчезают после компиляции. Во время выполнения у вас остаются виртуальные функции (полиморфизм) или dynamic_cast в лучшем случае.
Показать ещё 5 комментариев
0

Вместо того, чтобы проверять первый аргумент как Param<T>, вы можете вывести весь аргумент:

template<class Head, class... Tail>
void parseParameters(std::size_t& stride, Head&& head, Tail&&... tail)
{
    stride += head.size;
    parseParameters(stride, std::forward<Tail>(tail)...);
}

template<class... Args>
void createObject(Args&&... args)
{
    std::size_t stride = 0;
    parseParameters(stride, std::forward<Args>(args)...);
}

Вы также можете отключить различные перегрузки и включить других, если вы намерены использовать разные функции в зависимости от типа.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню