Я хочу вернуть некоторые значения из функции, и я хочу упаковать ее в кортеж. Итак, у меня есть две возможности для объявления функций:
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);
}
Эти функции являются эквивалентами?
Между этими функциями, которые вы предпочитаете?
std::forward_as_tuple()
создает кортеж Рекомендации. Так как вы возвращаете tuple<bool, string, int>
в любом случае, два в конечном итоге эквивалентны в этом случае, но я думаю, что первый подход яснее — использование forward_as_tuple()
когда вы не пересылаете ничего, это сбивает с толку.
Кроме того, как отметил Себастьян Редл в комментариях, make_tuple()
позволит компилятору выполнить копирование — в соответствии с пунктом 12.8 / 31 стандарта C ++ 11, в то время как forward_tuple()
не будет (так как то, что он возвращает, не имеет тот же тип, что и тип возврата функции).
Я предпочитаю,
std::tuple<bool, std::string, int> f()
{
...
return { false, "home", 0 };
}
Приведенный выше код на самом деле компилируется для меня в clang / libc ++ trunk. Как прокомментировал @AndyProwl в разделе комментариев, этого не следует делать, поскольку конструктор std :: tuple является явным, а возвращаемый через синтаксис список инициализации находится в контексте копирования-инициализации, следовательно, инициализация копирования-списка происходит сбой при совпадении явного конструктора.
Я не знаю причину, по которой проходит clang / libc ++, я предполагаю, что это ошибка в libc ++. Во всяком случае, грустно, что никто не может сделать это для кортежей …
Я думаю, я понял, как грустно (для меня, наконец) это вообще. Я привык к этому синтаксису, но нужно заранее знать, содержит ли возвращаемый тип явный конструктор в любое время для его работы.
Это действительно расширение 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
}