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