Is that an in or in/out parameter? Doxygen, C++
Asked Answered
H

2

9

If a pointer is passed to a function for read only, then this pointer is an IN parameter.

If a pointer is passed to a function for read only, but this function makes a copy of the pointer to have access to it in module related functions for read only operations, this pointer is still IN.

If the function still uses the pointer as read only, but the other module related functions use the pointer for write operations, what does that make the pointer? An IN parameter, but without const? An in/out parameter?

Example of what I mean:

class SteeringWheel {
        public: float rotation;
        public: SteeringWheel(void) {
                this->rotation = 0.f;
        }
};

class Car {
        private: SteeringWheel *steeringWheel;
        public:

        /**
         * @param[?] steeringWheel Is the steering wheel in or in/out? 
         */
        Car (SteeringWheel *steeringWheel) {
                this->steeringWheel = steeringWheel;
        }

        /**
         * @param[in] degree Steering amount in degrees.
         */
        void steer(float degree) 
        {
                this->steeringWheel->rotation += degree;
        }
};

int main(int argc, char **argv)
{
        SteeringWheel steeringWheel();

        /* car() uses steeringWheel as read only. */
        Car car(&steeringWheel);

        /* steer() uses steeringWheel from car() to write. */
        car.steer(50.f);

        return 0;
}
Hysterics answered 9/12, 2017 at 20:5 Comment(0)
L
27

I believe that the in and out specifiers do not exactly mean what you think. From the doxygen documentation of the param tag:

The \param command has an optional attribute, (dir), specifying the direction of the parameter. Possible values are "[in]", "[in,out]", and "[out]", note the [square] brackets in this description. When a parameter is both input and output, [in,out] is used as attribute.

The direction of the parameter usually mean the following:

  • in: The parameter is injected into the function as input, but not written to.
  • out: The parameter is injected into the function, but not as input. Rather, it is written to by the function.
  • in, out: The parameter is injected into the function as input and is eventually written to by the function.

In your example:

/**
* @param[?] steeringWheel Is the steering wheel in or in/out? 
*/
Car (SteeringWheel *steeringWheel) {
    this->steeringWheel = steeringWheel;
}

I think the steeringWheel parameter is in because you inject it and use it in your method. However, you never write to it (i.e. to the parameter itself), so it is not out. In other words, you only use your method to inject an address to your function, nothing else. The same apply for your second method, where you inject the degree parameter, but never write to it.

To clarify a bit more on the meaning of in and out, here is an example of an out parameter:

/**
 * @param[out] p_param We write to the parameter!
 */
void makeFour(int * p_param)
{
    *p_param = 4; // Out because of this line!
}

Notice that we write a new value directly into the parameter. This is the meaning of out: information comes out of the method through the parameter. You can now write:

int main()
{
    int myInt = 0;
    std::cout << myInt;    // prints 0.

    makeFour(&myInt); // p_param == &myInt here.
    std::cout << myInt;    // prints 4: the method wrote directly 
                           // in the parameter (out)!

    return 0;
}

Hope this helps!

Limber answered 17/12, 2017 at 14:43 Comment(0)
Y
4

It is not easy to decide, but I would still mark your parameter as in,out (or out), as it is a pointer to a non-const object, and you may change the state of that outside object directly or indirectly later - as in your example.

Marking it in hides the detail that the pointed SteeringWheel object may change later upon usage of Car.

Also, it can puzzle users why an input only pointer parameter is not marked const.

Making it in,out may not be accurate completely, but is surely more error prone.

An alternative could be something like the following (a note regarding the lifetime of the SteeringWheel should come handy here anyway):

    /**
     * @param[in] steeringWheel Pointer to the SteeringWheel object.
     * @warning The memory address of the pointed object is saved.
     * It must outlive this object, and can change upon usage of this object.
     */
    Car (SteeringWheel *steeringWheel) {
            this->steeringWheel = steeringWheel;
    }

But I would just probably stick with marking it in,out.

Specifying the direction of parameters in C++ may be complicated, and frankly speaking, I am not too much in favor of them, as having tokens for pointers, references, and the keyword for constness provide enough information in the signature on how a parameter may be used. Thus, marking it in the DoxyPress documentation is a bit redundant, not expressive enough (as your example shows), and may get out of sync with the implementation. Documenting parameter directions may play a bigger role in case of other languages that lack these additional constructs in function signatures.

Yardmaster answered 6/1, 2021 at 18:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.