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