-1

I stumbled upon this question (which is a different example). And most say a constructor does not return anything. However, why does my example work?

sequence(1, 2) is a constructor and obviously can be used on my machine. I use g++ and tried without option and with C++11 option. Both work in my case.

The example is from a course. I copy as is, no matter whether public makes sense or not, or something else.

Example:

#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;

void printer(int i) {
    cout << i << ", ";
}

struct sequence {
    int val, inc;
public:

    sequence(int s, int i) : val(s), inc(i) {
        cout << "Sequence(" << val << ", " << inc << ")" << endl;
    }

    operator int() const {//LINE I
        int r = val;
        cout << r << endl;
        return r;
    }
};

int main() {
    vector<int> v1(7);
    fill(v1.begin(), v1.end(), sequence(1, 2)); //LINE II
    for_each(v1.begin(), v1.end(), printer);
    return 0;
}

Result:

Sequence(1, 2)
1
1
1
1
1
1
1
1, 1, 1, 1, 1, 1, 1, 

Update

Thank you all for the answers. But I am still pretty confused, cannot get it into my head, probably missing proper terminology I think.

So far I think I understood:

  • sequence is a struct object
  • sequence(int, int) is a constructor definition and does not return anything
  • () operator on sequence simply returns the val value.

So why does it work:

  • the call to sequence(1,2) creates a temporary object that can be accessed and read
  • the () is used to fill the respective element. basically fill uses sequence() to get the value to fill in.
  • after fill has finished the temporary object is destroyed. It's scope is the scope of the function fill

Does that sound right so far?

Community
  • 1
  • 1
Ely
  • 10,860
  • 4
  • 43
  • 64
  • Define `work` please. What is `working` here and what did you expect? – VP. Aug 11 '15 at 07:21
  • Because you have an `operator int()` which is used to cast the `sequence` object to `int` – Vishal Aug 11 '15 at 07:22
  • 4
    Note, that `public` is really useless in your `struct` – DoctorMoisha Aug 11 '15 at 07:22
  • The constructor is not returning anything the *conversion operator* is when the constructed object is converted to an int in function `fill()`. – Galik Aug 11 '15 at 07:24
  • Hmm, I wonder what could have lead to downvotes. Is my question kind of *stupid*? – Ely Aug 11 '15 at 07:50
  • 2
    @Elyasin _"Is my question kind of stupid?"_ Yes, since a constructor doesn't `return` anything by definition. – πάντα ῥεῖ Aug 11 '15 at 08:51
  • @πάνταῥεῖ Well, that is my confusion. So far I think I understood. `sequence(int, int)` is not a constructor, but a function of a structure object that has the same name as the structure. The fact that a function has the same name as the object it is contained in and not returning a type by definition was/is pretty confusing; that looks like a constructor to me. Though in my code I am using such a function, and it returns an object that can be used and the program terminates with the expected result. I am still trying to digest the answers. I would not discourage people from asking to learn. – Ely Aug 11 '15 at 12:46
  • @DoctorMoisha That code is from an online course. Please disregard any superfluous code, or if it looks inefficient. – Ely Aug 11 '15 at 12:48
  • @Elyasin it's not a function that has the same name as a structure, it's an explicit type conversion which looks like a function. – TartanLlama Aug 11 '15 at 13:13
  • @TartanLlama Thank you dude. You are most helpful. However, I have difficulty to grasp that concept. Can you point me to some documentation or examples that I can use to study. I feel kind of lost. *It looks like a function, but it is not a function. It is an explicit type conversion.* - I reckon you're talking about the call `sequence(1,2)`, or do you mean the constructor `sequence(int, int)`? – Ely Aug 11 '15 at 14:29
  • 1
    @Elyasin [here](http://en.cppreference.com/w/cpp/language/explicit_cast) is some documentation on explicit type conversions. [Here](http://en.cppreference.com/w/cpp/language/cast_operator) is some on user-defined conversions. `sequence(1,2)` is an explicit type conversion which results in a temporary object of type `sequence` and can then be implicitly converted to `int` using the user-defined conversion operator. – TartanLlama Aug 11 '15 at 14:34
  • @TartanLlama you're amazing – Ely Aug 12 '15 at 09:05

5 Answers5

6

Because you have operator int() which converts your sequence class objects to 1. You can easily observe it as it prints 1 and a newline for every conversion.

dreamzor
  • 5,795
  • 4
  • 41
  • 61
  • So basically, it does not matter what object I put as that parameter. As long as it has a reasonable function operator it should work ? – Ely Aug 11 '15 at 07:26
4

sequence(1,2) is not a constructor call, it is an explicit type conversion using functional notation, resulting in a prvalue of type sequence. This is explained in [expr.type.conv]/1 (N3337):

A simple-type-specifier (7.1.6.2) or typename-specifier (14.6) followed by a parenthesized expression-list constructs a value of the specified type given the expression list.

[...]

If the expression list specifies more than a single value, the type shall be a class with a suitably declared constructor (8.5, 12.1), and the expression T(x1, x2, ...) is equivalent in effect to the declaration T t(x1, x2, ...); for some invented temporary variable t, with the result being the value of t as a prvalue.

The reason a sequence is acceptable as an int is that it provides an implicit conversion to int operator: operator int.

Community
  • 1
  • 1
TartanLlama
  • 63,752
  • 13
  • 157
  • 193
3

Constructor does not return anything means that you can't set the return value manually. However if you use sequence(1, 2) in your code, it creates temporary object of your type.

Then the compiler tries to convert that object to int. Since you have defined the int() operator, it succeeded.

Heavy
  • 1,861
  • 14
  • 25
  • So it creates one temporary object and when `fill` finishes the object is destroyed. In the meantime the function operator is used to get the numbers. Am I right with this? – Ely Aug 11 '15 at 07:27
  • When you call `fill`: first the `sequence` object is created, then it is being converted to `int`, this `int` value being passed to `fill`, then `sequence` is destroyed. – Heavy Aug 11 '15 at 07:31
  • 2
    @Heavy: No, the `sequence` object is passed into the fill function, and then this object is converted again and again inside the the function as the algorithm assigns from the `sequence` object to each element of the output range. – Benjamin Lindley Aug 11 '15 at 07:34
  • the vector contains `int` values, so you can't just pass random object into `fill` function. First compiler converts object into `int`, then passes the result into function. Although maybe you right, it depends on implementation. – Heavy Aug 11 '15 at 07:37
  • 3
    No, that is not correct. The signature of `std::fill` does not allow for that, as no checking is done on the value type of the iterator. Why do you think `1` is printed on 7 different lines in the OP's output? That is the conversion operator being called 7 times. – Benjamin Lindley Aug 11 '15 at 07:40
1

When you call sequence(1, 2) it is not the ctor who allocates memory for the temporary object, but code that the compiler generates. What the compiler generates is something like this pseudo code:

sequence *tmp = allocate_memory_from_stack_for_temp_object();
tmp->ctor(1, 2);
return *tmp;

As you can see the ctor is working on existing memory, so there is no need for the ctor function to return the constructed object. This is handled by some logic around the ctor. Of course the compiler also adds code to destroy the temporary object.

Werner Henze
  • 16,404
  • 12
  • 44
  • 69
  • So I can assume the constructor returns a reference to the object. Am I right with that assumption? – Ely Aug 11 '15 at 07:51
  • 1
    No, the constructor doesn't return anything. `sequence(1,2)` is *not* a constructor call. – TartanLlama Aug 11 '15 at 07:56
  • @elyasin No. The ctor does not return anything. And as TartanLlama stated in his answer `sequence(1,2)` is not a ctor call, it is more than that. It is definition of a tmp object and a call to the ctor for the tmp object and the expression returns the value of the constructed object. – Werner Henze Aug 11 '15 at 08:12
-3

Here you are overloading the operator() "function call operator" which returns int.(converting your object to int)

constructor doesn't return anything but by use of functors(function object) you can achieve that scenario. (sry if i am wrong here, anyone let me know ur comments)

Ex : lets say I have class A.

A obj(5);  // call to constructor.
int b = obj(6);  // call to overloaded operator() that you need to define
MKR Harsha
  • 105
  • 9