Вопрос

I have a problem providing the correct overloading for const and not const getter functions with the new return value syntax.

In my class PhysicalNode I have defined a getter function with the new return value syntax. This is needed as the return type of the getter depends on the type of the member.

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;
}

However I want now to also provide this method as const.

Normally I would use function overloading to define my const and not const getter function like that.

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

I have tried the following function declaration but it does not work:

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

The compile error is:

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'

How do I need to define the function declaration to define this function as constant.

Это было полезно?

Решение

If you really really want to use this notation and the standard type traits, you should write your const overload this way:

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

Otherwise you would be returning a reference to non-const, which is clearly wrong considering your member function is const-qualified.

Notice, however, that type traits are not really needed here (if EnergySolver is just a regular type and not a reference type alias):

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

But even decltype is unnecessary. If your real program is not more complicated than the example you are showing, this is enough:

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

Другие советы

It's unclear why the "traditional" method is not good for your purposes.

The machination with decltype and add/remove trickery is to cover ground for templates that want to be overly generic. Where you must deal with unknown types and ones you have no control over.

For the usual situations it is way clearer to just add a few typedefs and use those directly.

For your attempt, IMO you use it incorrectly, either try const auto& in front, or auto in front and assemble the type all the way after the ->, combininge remove_reference, then add_const then add_lvalue_reference, it may work, though would make head spin.

decltype(PhysicalNode::energySolver_) is plain EnergySolver, not const EnergySolver even though the method is const, since the expression doesn't use this, which is what that const qualifier really affects. And you're not allowed to use decltype(this->energySolver_) in this context since PhysicalNode is not yet complete.

You'll have to do something like -> const decltype(PhysicalNode::energySolver_)&; or -> std::add_lvalue_reference<std::add_const<decltype(PhysicalNode::energySolver_)>::type>::type; or something in between.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top