2013-06-12 5 views
2

У меня есть проблема, обеспечивающая правильную перегрузку для функций const и not const getter с новым синтаксисом возвращаемого значения.Перегрузка синтаксиса возвращаемого значения const и не const function

В моем классе PhysicalNode Я определил функцию геттера с новым синтаксисом возвращаемого значения. Это необходимо, так как тип возврата получателя зависит от типа элемента.

class PhysicalNode { 
private:  
    solver::EnergySolver energySolver_; ///< The energy solver of this node 
    //solver::EnergyMomentumSolver energySolver_ 
public: 
    auto getEnergySolver()-> typename 
     std::add_lvalue_reference<decltype(PhysicalNode::energySolver_)>::type; 
} 

Однако я хочу также предоставить этот метод как const.

Обычно я бы использовал функцию перегрузки для определения функции const, а не const getter.

class PhysicalNode { 
private:  
    solver::EnergySolver energySolver_; 
public: 
    const solver::EnergySolver& getEnergySolver() const; 
    solver::EnergySolver& getEnergySolver(); 
} 

Я попробовал следующее объявление функции, но она не работает:

const auto getEnergySolver() const-> typename 
     std::add_lvalue_reference<decltype(PhysicalNode::energySolver_)>::type; 

Ошибка компиляции является:

PhysicalNode.cpp:72: error: invalid initialization of reference of type 
'std::__add_lvalue_reference_helper<LbmLib::solver::EnergySolver, true, 
false>::type {aka LbmLib::solver::EnergySolver&}' from expression of type 
'const LbmLib::solver::EnergySolver' 

Как мне нужно определить объявление функции для определения эта функция постоянна.

+0

Почему вы используете 'typename'? Является ли 'PhysicalNode' шаблоном класса? –

+0

Потому что я не получил работу decltype. Но из-за вашего ответа я знаю теперь, как этого избежать :) – tune2fs

+0

ОК, рад, что это помогло :) –

ответ

4

Если вы действительно хотите использовать эти обозначения и стандартные черты типа, вы должны написать перегрузки const таким образом:

auto getEnergySolver() const -> 
    std::add_lvalue_reference< 
     std::add_const<decltype(PhysicalNode::energySolver_)>::type 
//  ^^^^^^^^^^^^^^ 
     >::type; 

В противном случае вы бы возвращающей ссылку на непредставленных const, что явно неверно, учитывая вашу функцию-член const -qualified.

Обратите внимание, однако, на самом деле не нужны, что черты типа здесь (если EnergySolver просто обычный тип, а не ссылочный тип псевдоним):

auto getEnergySolver()-> decltype(PhysicalNode::energySolver_)&; 
auto getEnergySolver() const -> decltype(PhysicalNode::energySolver_) const&; 

Но даже decltype ненужно. Если реальная программа не сложнее, чем, например, вы показываете, это достаточно:

auto getEnergySolver()-> solver::EnergySolver&; 
auto getEnergySolver() const -> solver::EnergySolver const&; 
+0

В чем преимущество объявления геттеров таким образом? кажется чрезмерно сложным – paulm

+0

@paulm: В этой конкретной ситуации нет никакой пользы, я думаю, что OP просто хотел попробовать этот новый синтаксис –

0

decltype(PhysicalNode::energySolver_) ясно EnergySolver, не const EnergySolver даже если метод const, поскольку выражение не использует this, что и что const классификатор действительно влияет. И вам не разрешено использовать decltype(this->energySolver_) в этом контексте, так как PhysicalNode еще не завершен.

Вам нужно будет сделать что-то вроде -> const decltype(PhysicalNode::energySolver_)&; или -> std::add_lvalue_reference<std::add_const<decltype(PhysicalNode::energySolver_)>::type>::type; или что-то среднее между ними.

0

Неясно, почему «традиционный» метод не подходит для ваших целей.

Махинация с помощью decltype и добавление/удаление обмана - это покрытие земли для шаблонов, которые хотят быть слишком универсальными. Где вы должны иметь дело с неизвестными типами и те, на которые вы не имеете контроля.

Для обычных ситуаций проще всего добавить несколько typedefs и использовать их напрямую.

Для вашей попытки, IMO использовать его неправильно, либо попытаться константный авто & впереди, или авто спереди и собрать тип весь путь после -> combininge remove_reference, затем add_const затем add_lvalue_reference, он может работать, хотя и заставит голову вращаться.

Смежные вопросы