Может ли функция возвращать несколько значений разных типов?
Он подумал, что было бы интересно вернуть несколько значений (с разными типами!) Из вызова функции C++.
Поэтому я посмотрел вокруг, чтобы найти какой-то пример кода, но, к сожалению, не смог найти ничего подходящего для этой темы.
Я хотел бы функцию, как...
int myCoolFunction(int myParam1) {
return 93923;
}
работать с различными типами, чтобы вернуть несколько различных типов значений, таких как
?whatever? myCoolFunction(int myParam1) {
return { 5, "nice weather", 5.5, myCoolMat }
}
Итак, возможно ли что-то подобное с использованием C++(моя идея состояла в том, чтобы использовать специальный вектор AnyType, но я не смог найти пример кода), или я должен остаться на вызовах такого типа? (увидеть ниже)
void myCoolFunction(cv::Mat &myMat, string &str){
// change myMat
// change str
}
Примечание. Таким образом, порядок и количество возвращаемых элементов будут одинаковыми каждый раз - > Набор остается идентичным (например, 1.:double, 2.:int
в каждом случае)
5 ответов
Если вы хотите вернуть несколько значений, вы можете вернуть экземпляр класса, заключающий в себе разные значения.
Если вы не заботитесь о потере семантики, вы можете вернуть std::tuple
1:
auto myCoolFunction(int myParam1) {
return std::make_tuple(5, "nice weather", 5.5, myCoolMat);
}
Если вы хотите заставить типы (например, есть std::string
вместо const char *
):
std::tuple<int, std::string, double, cv::Mat> myCoolFunction(int myParam1) {
return {5, "nice weather", 5.5, myCoolMat};
}
В обоих случаях вы можете получить доступ к значениям, используя std::get
:
auto tup = myCoolFunction(3);
std::get<0>(tup); // return the first value
std::get<1>(tup); // return "nice weather"
1 Если у вас есть компилятор, совместимый с C++17, вы можете использовать вывод аргументов шаблона и просто вернуть std::tuple{5, "nice weather", 5.5, myCoolMat}
,
Конечно, это возможно, используя std::tuple
, доступно в стандартной библиотеке начиная с C++11:
#include <tuple>
std::tuple<int, std::string, double, cv::Mat>
myCoolFunction(int myParam1) {
return { 5, "nice weather", 5.5, myCoolMat }
}
Если вам разрешено использовать код C++14, вам даже не нужно объявлять тип:
#include <tuple>
auto myCoolFunction(int myParam1) {
return std::make_tuple(5, "nice weather", 5.5, myCoolMat);
}
и вот доказательство того, что обе эти версии компилируются (без cv::Mat
- Я не думаю, что GodBolt это доступно).
Заметки:
- Если вы используете
std::make_tuple
типы могут не соответствовать вашим ожиданиям. Например, в этом случае вы получитеchar *
хотя при явном определении кортежа его можно заставитьstd::string
как у меня выше. Обычно это не проблема. - Если некоторые данные велики, вы можете попробовать
std::move
это, чтобы избежать копирования всей вещи, например, передаваяstd::move(myCoolMat)
,
Вы можете вернуть структуру или использовать std::tuple.
Используя struct, вы можете сделать:
myStruct create_a_struct() {
return {20, std::string("baz"), 1.2f};
}
И с std:: tuple
std::tuple<int, std::string, float> create_a_tuple() {
return {20, std::string("baz"), 1.2f};
}
(Ответьте за забаву действительно и продемонстрируйте силу C++, а не что-нибудь еще.)
Одним из способов, который на самом деле является довольно злым, так как вы обременяете сайт звонков распаковкой контента, является
std::shared_ptr<void>
как тип возвращаемого значения. Это разрешено с std::shared_ptr
поддерживает стирание типа. (К несчастью, std::unique_ptr
не так, вы должны исключить это.)
Очевидно, что в функции вам нужно будет использовать std::make_shared
или похожие.
Ссылка: почему shared_ptr
Возвращает std:: vector из std:: option, где std:: variable является параметризованным шаблоном для вашего выбора типов. Если какой-либо тип действительно возможен, я не уверен, почему вы делаете это со структурами, а не просто записываете в область памяти; Отсутствие детерминированной концепции объектов и типов в структуре имеет низкую ценность.