Должен ли я использовать boost:: variant?

Моя виртуальная функция может возвращать либо один T, либо std::vector<T>. Стоит ли возвращать boost::variant<T, std::vector<T>> в этом случае или лучше всегда возвращать std::vector<T>? Что выглядит лучше и имеет наименьшие потери производительности? Быстрее ли использовать вариант, когда возвращается одно значение?


person lizarisk    schedule 08.07.2013    source источник
comment
Забудьте о производительности, пока ваш профилировщик не скажет вам, что у вас узкое место. Что касается дилеммы, использовать ли vector<T> или variant<T, vector<T>>, я думаю, что невозможно дать ответ, не зная семантики вашей функции.   -  person Andy Prowl    schedule 08.07.2013
comment
Будьте проще, верните std::vector, в обоих случаях вам нужно будет проверить, есть ли у вас один элемент T (size() == 1) или много.   -  person alfC    schedule 08.07.2013
comment
Я так не думаю, статический посетитель не должен выполнять эту проверку.   -  person lizarisk    schedule 08.07.2013
comment
@lizarisk, я имею в виду, по крайней мере, с точки зрения кодирования (в любом случае что-то нужно делать во время выполнения, верно?). Если у вас нет всей инфраструктуры для того, чтобы что-то делать с уже установленным variant, то это будет проблемой. (Я не говорю, что вариант решения не является более элегантным в долгосрочной перспективе, просто даю практическую рекомендацию)   -  person alfC    schedule 08.07.2013
comment
@lizarisk, как вы думаете, как посетитель работает во время выполнения? Эквивалентный чек.   -  person Yakk - Adam Nevraumont    schedule 08.07.2013
comment
Возможно, я не ясно выразился, но возвращаемый тип (либо T, либо std::vector<T>) зависит от реализации виртуальной функции, а не от какого-либо условия внутри самой функции. Так что это часть интерфейса, поэтому я подумал о boost::variant как о решении.   -  person lizarisk    schedule 08.07.2013
comment
boost::static_visitor работает во время компиляции, поэтому здесь нет накладных расходов и виртуальных функций.   -  person lizarisk    schedule 08.07.2013
comment
@AndyProwl, я часто сталкиваюсь с этой дилеммой, например, при поиске всех корней функции. У него может быть один или несколько (или ни одного), и, конечно, случай с одним корнем является прототипическим в том смысле, что набор последующих операций выполняется в одном (или нескольких корнях) (представьте это как разветвление), в прототипном случае std::vector кажется пустой тратой времени, потому что все нужно повторять позже. Так что это может быть семантическим примером (если только лизариск не даст другой). (lizarisk, пожалуйста, опубликуйте пример.)   -  person alfC    schedule 08.07.2013
comment
Я упомянул виртуальные функции, потому что у меня очень широкий интерфейс с множеством реализаций. Большинство из них всегда возвращают одно значение, и я подумал, что это может быть особый случай, который отражается в интерфейсе.   -  person lizarisk    schedule 08.07.2013
comment
Я так не думаю, если правильная функция для вызова (путь выполнения) отправляется во время компиляции, не должно быть дополнительных накладных расходов. Что еще вы подразумеваете под посещением?   -  person lizarisk    schedule 08.07.2013


Ответы (1)


Помимо проблем с производительностью, это зависит от семантики вашей функции или, точнее, от возвращаемого значения.

Вам часто нужно различать (с точки зрения пути кода) случай, когда возвращается только один T, и случай с несколькими значениями? Или простой for(auto t : create_T_orTs()) { ... } может сделать правильную вещь в любом случае?

Я интуитивно чувствую, что первое менее вероятно, чем второе, и, поскольку variant<> имеет синтаксическую «цену», я бы выбрал KISS и использовал std::vector<T>, если только нет веской семантической причины для этого. различать случаи с одним и несколькими значениями.

person Fabio Fracassi    schedule 08.07.2013