tuple
в boost и TR1/С++ 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-совместимые конструкции выше, будет ли что-нибудь в полной версии С++ 0x или boost?
В идеале это:
- Позвольте мне использовать инициализацию, а не просто назначение
- пусть вызывающий выбирает имена для возвращаемых переменных
- не создавать дополнительные копии
- работает как для переменных стека, так и для членов класса
- возможно, это большая сумасшедшая библиотека шаблонов, но имеет разумный синтаксис для автора звонков и функций