Какой лучший способ вернуть кортеж из функции в C ++ 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);
}

Эти функции являются эквивалентами?
Между этими функциями, которые вы предпочитаете?

24

Решение

std::forward_as_tuple() создает кортеж Рекомендации. Так как вы возвращаете tuple<bool, string, int> в любом случае, два в конечном итоге эквивалентны в этом случае, но я думаю, что первый подход яснее — использование forward_as_tuple() когда вы не пересылаете ничего, это сбивает с толку.

Кроме того, как отметил Себастьян Редл в комментариях, make_tuple() позволит компилятору выполнить копирование — в соответствии с пунктом 12.8 / 31 стандарта C ++ 11, в то время как forward_tuple() не будет (так как то, что он возвращает, не имеет тот же тип, что и тип возврата функции).

21

Другие решения

Я предпочитаю,

std::tuple<bool, std::string, int> f()
{
...
return { false, "home", 0 };
}

РЕДАКТИРОВАТЬ 1

Приведенный выше код на самом деле компилируется для меня в clang / libc ++ trunk. Как прокомментировал @AndyProwl в разделе комментариев, этого не следует делать, поскольку конструктор std :: tuple является явным, а возвращаемый через синтаксис список инициализации находится в контексте копирования-инициализации, следовательно, инициализация копирования-списка происходит сбой при совпадении явного конструктора.

Я не знаю причину, по которой проходит clang / libc ++, я предполагаю, что это ошибка в libc ++. Во всяком случае, грустно, что никто не может сделать это для кортежей …

Я думаю, я понял, как грустно (для меня, наконец) это вообще. Я привык к этому синтаксису, но нужно заранее знать, содержит ли возвращаемый тип явный конструктор в любое время для его работы.

РЕДАКТИРОВАТЬ 2

Это действительно расширение libc ++, для получения дополнительной информации посмотрите ответ Говарда Хиннанта здесь: https://stackoverflow.com/a/14963014.

В настоящее время он также открыт в списке ошибок libc ++: http://llvm.org/bugs/show_bug.cgi?id=15299.

Это соответствующее предложение: Даниэль Крюглер, Улучшение пары и кортежа.

Вкратце это то, что происходит с libc ++:

#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
}
5

По вопросам рекламы [email protected]