2

Is it possible to use the converting constructor rather than copy constructor to return object from a function even if there is no RVO evolved(Suppose that the compiler is not supporting any such kind of optimizations)? The point of the question is what is the C++ std having told, could anyone tell me? I got the gcc and compiled the code below with several questions in the comment either.



    class A
    {
    public:
        A(int) {};
        A(int, int) {};

    private:
        A(const A &) = delete;
        A & operator = (const A &) = delete;
    };

    A foo(void)
    {// All the CEs below are all the same, which is 'using the deleted function 'A::A(const A&)''.
        //return(0); // Not compiled.
        //return(A(0)); // Not compiled. ok since the A isn't be copy-able.
        //return {0};  // Compiled. Is it a bug of the compiler?
        //return({0}); // Not compiled. What happened when returns in '()' implemented?
        //return 0;  // Not compiled. What happened when returns without '()' and '{}' implemented?
        //return ({0, 0}); // Not compiled.
        return {0, 0}; // Compiled. Realy??

    /*
      1. What are the differences in 'return 0', 'return {0}', 'return(0)' and 'return({0})'?
      2. Is it any possible to do conversion from source type object 'which is 'int' in this sample' to returning type of
    the function directly with only ONE constructor call even if the compiler has no any copying eliminating optimization
     but full compatibility with STD? Note that the function 'foo' here has no returning object accepter.
    */
    }

    int main(void)
    {
        foo(); // Note that there is no accepter of 'A' here, it's not discussing purpose at this topic of the post.
    }

    // compiling with the gcc ver. 4.8.1.

BenMorel
  • 34,448
  • 50
  • 182
  • 322

1 Answers1

2

Yes, it's perfectly valid to call a converting constructor in a return statement, if you use a braced-init-list to initialize the returned object.

The C++11 standard says this in 6.6.3 [stmt.return]:

The value of the expression is implicitly converted to the return type of the function in which it appears. A return statement can involve the construction and copy or move of a temporary object (12.2). [Note: A copy or move operation associated with a return statement may be elided or considered as an rvalue for the purpose of overload resolution in selecting a constructor (12.8). — end note] A return statement with a braced-init-list initializes the object or reference to be returned from the function by copy-list-initialization (8.5.4) from the specified initializer list. [Example:

std::pair<std::string,int> f(const char* p, int x) {
  return {p,x};
}

end example]

In the other commented-out return statements you create a temporary object which would then need to be copied to the returned object, which requires an accessible copy ctor.

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • Thanks but what i attempt to ask is 'If the copy-constructor AND move-constructor' are all inaccessible, like privated or =deleted, SHOULD the code still BE ALLOWED to be compiled? Why the code wouldn't be accepted by the compiler if i implemented parentheses outside of the braces? It seems that at least the gcc will treat the listed returns in the code sample as different things. – unituniverse Oct 05 '13 at 17:02
  • OK, I understand the reference to RVO now (N.B. RVO never changes whether code compiles or not, if a copy constructor is needed then it's still needed even if RVO happens.) Yes, the code is valid, like I said. I'll update the answer. – Jonathan Wakely Oct 05 '13 at 19:46
  • Thank you. I'm still searching for the answer about the sample you provided. the question is if the 'return {p, x};' will act like std::pair(p, x) but is analized (by the compiler) as std::pair(std::pair(p,x)); – unituniverse Oct 05 '13 at 21:23
  • , or there is no copy/rv-move constructing(even if without RVO evolved in) at all when uses a braced-init-list as the return. If the answer is the latter one then everything make sense, or it just be the bug of the compiler which should have been considered. – unituniverse Oct 06 '13 at 03:23
  • The latter, there is no copy/move when the return object is initialized with a braced-init-list. – Jonathan Wakely Oct 06 '13 at 03:55