user11910061
user11910061

Reputation:

Why can I only create a function alias using the type auto?

I have the following static function defined in the utilities namespace.

class InvalidDecimalPlace {};

namespace utilities
{
    double static RoundToNthDecimalPlace(double number, int decimalPlace)
    {
        if (decimalPlace < 0 )
            throw InvalidDecimalPlace();
        else if (decimalPlace == 0)
            return static_cast<int>(number);

        int powerUp = std::pow(10, decimalPlace);
        number *= powerUp;
        int numberWithoutDecimals = static_cast<int>(number);
        return numberWithoutDecimals / static_cast<double>(powerUp);

    }
};

In another file I want to alias this function so I don't need to qualify it with the scope resolution operator. Somebody told me to do the following:

auto& RoundToNDecimalPlace = utilities::RoundToNthDecimalPlace;
// Or the following, const auto RoundToNDecimalPlace = utilities::RoundToNthDecimalPlace;

I noticed that this only works with auto though. Why is this the case? For instance, why doesn't the following work?

double& RoundToNDecimalPlace = utilities::RoundToNthDecimalPlace;

Upvotes: 2

Views: 128

Answers (3)

eerorika
eerorika

Reputation: 238351

Why can I only create a function alias using the type auto?

What you've declared with auto& is a reference to function. The commented auto would define a pointer to function instead.

double is not a function (instead, it is an object type), so it is the wrong type to use for referring to a function. The correct type of utilities::RoundToNthDecimalPlace is double (double, int). So the equivalent declaration to auto would be:

double (*RoundToNDecimalPlace)(double, int) = utilities::RoundToNthDecimalPlace;

However for clarity, I recommend a type alias:

using RoundingFunction = double (double, int);
RoundingFunction* RoundToNDecimalPlace = utilities::RoundToNthDecimalPlace;

So in conclusion: No, you don't need to use auto, but you cannot use a wrong type either.

Upvotes: 1

templatetypedef
templatetypedef

Reputation: 372794

Since utilities::RoundToNthDecimalPlace is a function, its type is

double (double, int);

This is the type of a function taking in a double and returning an int. Notice that this isn’t the same as type double, so you can’t bind a reference of type double& to it.

When you use auto&, C++ is properly inferring the type of the variable to be

double (&) (double, int)

which is a reference to a function taking in a double and an int that then returns a double.

That being said, there’s no need to use a reference variable here. If you want to be able to access that one function more concisely, just say

using utilities::RoundToNthDecimalPlace;

Hope this helps!

Upvotes: 3

Pete Becker
Pete Becker

Reputation: 76295

The type of the function is not double, it's double (&) (double, int) which is, I think, what you end up with when you use auto. But the name of a function decays into a pointer, so the "usual" approach (inherited from C) would be to create a pointer to that function, like this:

double (*fn)(double, int) = utilities::RoundToNthDecimalPlace;

Now you can use `find just like you'd use the original function:

double result = fn(1.0, 3);

Upvotes: 1

Related Questions