Как я могу вернуть временный из моего специализированного std :: max? - PullRequest
0 голосов
/ 26 июля 2010

Hallo! Я хочу специализироваться std::max для типа фракции для конкретной платформы.

Прототип для конкретной системы max, который я хочу использовать, выглядит следующим образом:

fract builtin_max(fract a, fract b);

Моя идея для специализированного std::max выглядит так:

template <> inline
const fract& std::max<fract>(const fract& a, const fract& b) {
    return builtin_max(a, b);
}

Однако компилятор по понятным причинам жалуется на возвращение ссылки на локальный временный объект. Можно ли как-то обойти это?

Ответы [ 3 ]

3 голосов
/ 26 июля 2010

Вы можете вернуть результат по значению. Тогда, скорее всего, состоится RVO . В конце вы получите поведение, как вы хотели.

И я бы изменил builtin_max объявление на

fract builtin_max(const fract& a, const fract& b);

Это поможет компилятору распознать возможность для RVO.

Наконец, ваш max будет выглядеть так:

template <> 
fract std::max<fract>(const fract& a, const fract& b) {
    return builtin_max(a, b);
}
1 голос
/ 26 июля 2010

Если вы можете изменить builtin_max, то путь состоит в том, чтобы изменить сигнатуру так, чтобы она брала две константные ссылки и возвращала константную ссылку (если тип не является достаточно маленьким, чтобы передача по значению имела смысл), и перегрузка для неконстантной версии. Тогда вы можете легко адаптировать подписи: просто переадресовать звонок.

fract const & builtin_max( fract const & lhs, fract const & rhs );
fract & builtin_max( fract & lhs, fract & rhs );

template <>
fract const & std::max( fract const & lhs, fract const & rhs ) {
   return builtin_max( lhs, rhs );
}
template <>
fract & std::max( fract & lhs, fract & rhs ) {
   return builtin_max( lhs, rhs );
}

Еще одна простая вещь, которую вы можете сделать, это не перегрузить std::max, а создать собственную функцию max в вашем пространстве имен. Все неквалифицированные использования max, которые принимают значения fract, найдут вашу функцию max, прежде чем они попытаются использовать шаблон std::max по умолчанию. Опять же, это не будет работать для полностью квалифицированных звонков на std::max:

namespace x {
   class fract;
   fract max( fract lhs, fract rhs ) { return builtin_max( lhs, rhs ); }
}
// force a link time error if fully qualified std::max is used (undefined)
// instead of silently getting std::max to use < (if it is defined)
// if there is no operator<( fract const &, fract const & ), leave this out
// to get an earlier compile time error
template <> fract const & std::max( fract const &, fract const & );
template <> fract & std::max( fract &, fract & );

int main() {
   using namespace std;
   fract a,b;
   max( a, b );          // x::max
   // std::max( a, b )   // ouch, link time error
}
0 голосов
/ 06 октября 2010

Моим решением было сделать это так:

fract std::max(fract a, fract b) {
    return builtin_max(a, b);
}

Супер просто и работает так, как я хочу :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...