Какой лучший способ вернуть кортеж из функции в С++ 11?
Я хочу вернуть некоторые значения из функции, и я хочу упаковать ее в кортеж. Поэтому у меня есть две возможности для объявления функции:
std::tuple<bool, string, int> f()
{
...
return std::make_tuple(false, "home", 0);
}
и
std::tuple<bool, string, int> f()
{
...
return std::forward_as_tuple(false, "home", 0);
}
Эти функции эквивалентны?
Между этими функциями, которые вы предпочитаете?
Ответы
Ответ 1
std::forward_as_tuple()
создает кортеж ссылок. Так как вы все равно возвращаете tuple<bool, string, int>
, в этом случае они становятся эквивалентными, но я думаю, что первый подход более понятен - использование forward_as_tuple()
, когда вы не пересылаете что-либо, путается.
Кроме того, как упоминалось в комментариях Себастьяном Редлом, make_tuple()
разрешает компилятору выполнять копирование в соответствии с параграфом 12.8/31 стандарта С++ 11, тогда как forward_tuple()
не будет (поскольку то, что оно возвращает не имеет того же типа, что и тип возвращаемой функции).
Ответ 2
Я предпочитаю,
std::tuple<bool, std::string, int> f()
{
...
return { false, "home", 0 };
}
EDIT 1
Вышеприведенный код фактически компилируется для меня под связью clang/libС++. Поскольку @AndyProwl прокомментировал раздел комментариев, это не следует, поскольку конструктор std:: tuple является явным, а возврат через синтаксис списка инициализации - в контексте инициализации копии, а следовательно, и в инициализации списка копий, который не выполняется, когда явный конструктор сопоставляется.
Я не знаю, почему происходит clang/libС++, я полагаю, что это ошибка в libС++. Во всяком случае, это грустно, что нельзя делать это для кортежей...
Думаю, я понял, как грустно (для меня, наконец) это вообще. Я привык к этому синтаксису, но нужно заранее знать, будет ли возвращаемый тип содержать явный конструктор в любое время для его работы.
EDIT 2
Это действительно расширение libС++, для получения дополнительной информации, проверка Howard Hinnant здесь: fooobar.com/info/237312/....
В настоящее время он также открыт в списке ошибок libС++: http://llvm.org/bugs/show_bug.cgi?id=15299.
Это соответствующее предложение: Даниэль Крюглер, Улучшение пары и кортежа.
Короче говоря, это происходит с libС++:
#include <tuple>
#include <string>
struct S
{
explicit S(int) {}
};
int main()
{
std::tuple<int, std::string> t1 = { 1, "hello" }; // ok
std::tuple<std::string> t2 = "hello"; // ok
std::tuple<int, S> t3 = { 1, 1 }; // fail: an *element* is to be constructed explicitly
}