0

I'm studying functional operators and can't understand why code snippets like this compile:

class Pocket
{
    int value;
public:
    Pocket(int value) :value(value) {}
    int getValue() const
    {
        return value;
    }
    operator int() const
    {
        return value;
    }
    bool operator<(const Pocket & _Right) const
    {
        return value < _Right.value;
    }
};

int main() {
    Pocket mynumbers1[] = { 3, 9, 2, -4, 4 };
    Pocket mynumbers2[] = { 3, 9, 5, 0, 4 };
    vector<Pocket> v1(mynumbers1, mynumbers1 + 5);
    vector<Pocket> v2(mynumbers2, mynumbers2 + 5);
    vector<Pocket> v3(5, 0);
    transform(v1.begin(), v1.end(), v2.begin(), v3.begin(), minus<Pocket>());
    return 0;
}

My reasoning is that when you call the minus<Pocket> operator inside transform, the whole thing would reduce to a subtraction between two Pockets. As you can see, the class doesn't defines a proper operator-, only an operator<, which should be useless in this case, and a conversion to int, which shouldn't even be considered since both arguments are of the same type.

So what am I missing?

4
  • 1
    The compiler will deduce a possible conversion for minus() using the explicit cast operator of Pocket. Commented Jan 1, 2019 at 11:26
  • Where did you gather the user defined conversion isn't going to come into play? Commented Jan 1, 2019 at 11:27
  • "and a conversion to int, which shouldn't even be considered since both arguments are of the same type" This statement is very unclear, can you elaborate more please why you think this should apply? Commented Jan 1, 2019 at 11:32
  • 4
    Your reasoning is incorrect - the compiler will use the user-defined conversion you have specified. To demonstrate that, remove the operator int from the Pocket class - you will see that the code no longer compiles. Commented Jan 1, 2019 at 11:33

1 Answer 1

1

The user-defined conversion function which makes the following initializations possible in your code:

Pocket mynumbers1[] = { 3, 9, 2, -4, 4 };
Pocket mynumbers2[] = { 3, 9, 5, 0, 4 };

will also be used by the compiler in the transform call when applying the minus to the given range :

transform(v1.begin(), v1.end(), v2.begin(), v3.begin(), minus<Pocket>());

If you were to remove the operator int() const conversion function neither the initializations nor the transform would work.

However, if you were to make the conversion function explicit, it would work for initializations but not for the transform. See demo here.

The relevant section in the standard for this:

15.3.2 Conversion functions [class.conv.fct]
...
2. A conversion function may be explicit, in which case it is only considered as a user-defined conversion for direct-initialization. Otherwise, user-defined conversions are not restricted to use in assignments and initializations.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.