Как инициализировать с несколькими возвращаемыми значениями в C++ (0x)

tuple в повышении и TR1/c ++ 0x предоставляет удобное (устройству записи функции) метод для возвращения двух значений от функции - однако это, кажется, повреждает одну основную функцию языка для вызывающей стороны: способность просто использовать функцию для инициализации переменной:

T happy();
const auto meaningful_name(happy()); // RVO means no excess copies

но для:

tuple<T,U> sad();

мы любой должен сдать способность выбрать понятное имя для наших возвращаемых значений и использование get<n>() везде:

const auto two_unrelated_things(sad());

или сделайте временный файл:

const auto unwanted_named_temporary(sad());
const auto one_name(get<0>(unwanted_named_temporary));
const auto two_name(get<1>(unwanted_named_temporary));

или переключатель от инициализации до присвоения, которое только работает, когда типы являются присваиваемыми, и повреждения auto:

tuple_element<0, decltype(sad())>::type one_mutable; // there might be a less
tuple_element<1, decltype(sad())>::type two_mutable; // verbose way
tie(one_mutable,two_mutable) = sad();

или сделайте что-то неестественное к локальному классу:

const struct ugh { 
  ugh( decltype(sad()) rhs ) : one_name(get<0>(rhs)), two_name(get<1>(rhs)) {}
  const tuple_element<0, decltype(sad())>::type one_name;
  const tuple_element<1, decltype(sad())>::type two_name;
} stuff(sad()); // at least we avoid the temporary and get initialization

Существует ли лучший путь? Я использую совместимые конструкции VC10 выше, был бы что-нибудь в полном C++ 0x или справка повышения?

Идеально это было бы:

  • позвольте мне использовать инициализацию, не просто присвоение
  • позвольте вызывающей стороне выбрать названия возвращенного - в переменные
  • не делают дополнительные копии
  • работа и для переменных стека и для участников класса
  • возможно будьте крупной сумасшедшей библиотекой шаблонов, но имейте нормальный синтаксис для вызывающей стороны и разработчика программной реализации функции
11
задан BCoates 7 August 2010 в 08:52
поделиться

1 ответ

std::tuple<Type1, Type2> returnValue = sad();
Type1& first = std::get<0>(returnValue);
Type2& second = std::get<1>(returnValue);

Я не уверен, что означает ваша четвертая пуля, но всех остальных это устраивает.

* edit: Основываясь на вашем комментарии выше, я понял, что вы имели в виду под четвертым маркером.

struct Object {
    Object(const std::tuple<Type1, Type2>& t) : value(t) { }
    Type1& First() { return std::get<0>(value); }
    Type2& second() { return std::get<1>(value); }
private:
    std::tuple<Type1, Type2> value;
}

При необходимости измените.

Вы также можете вообще не использовать std :: tuple , если возвращаемые значения настолько не связаны, что вам придется разделить их, чтобы их можно было использовать разумно. Люди годами возвращали struct s с полями с разумными именами или путем принятия ссылочных параметров для вывода.

Кстати, вы, кажется, влюблены в auto . Не надо. Это отличная функция, но это не способ ее использования. Ваш код будет неразборчивым, если вы время от времени не будете указывать типы.

2
ответ дан 3 December 2019 в 12:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: