copy ctor being private and compilation error

Discussion in 'C++' started by subramanian100in@yahoo.com, India, Aug 3, 2010.

  1. , India

    , India Guest

    Consider the following program x.cpp:

    #include <cstdlib>
    #include <iostream>

    using namespace std;

    class Test
    {
    public:
    explicit Test(int arg = 10);
    ostream& writeTo(ostream& os) const;
    private:
    Test(const Test& rhs);
    int val;
    };

    inline Test::Test(int arg) : val(arg)
    {
    cout << "Test one-argument-ctor called" << endl;
    }

    inline ostream& Test::writeTo(ostream& os) const
    {
    return os << val;
    }

    inline ostream& operator<<(ostream& os, const Test& obj)
    {
    return obj.writeTo(os);
    }

    int main()
    {
    const Test& ref = Test();
    cout << ref << endl;

    return EXIT_SUCCESS;
    }

    When I compile this program as
    g++ -std=c++98 -pedantic -Wall -Wextra x.cpp

    I get the following compilation error:
    x.cpp: In function `int main()':
    x.cpp:12: error: `Test::Test(const Test&)' is private
    x.cpp:33: error: within this context

    Though the copy ctor of Test is private, the statement
    const Test& ref = Test();
    involves only taking a 'const reference' to the temporary Test object
    created by Test() on the RHS. Since only a reference is made, why does
    this statement require the copy ctor ?
    Kindly clarify, if necessary with a program example.

    Thanks
    V.Subramanian
     
    , India, Aug 3, 2010
    #1
    1. Advertising

  2. , India

    Ian Collins Guest

    On 08/ 3/10 04:12 PM, , India wrote:
    > Consider the following program x.cpp:
    >

    <snip>
    >
    > int main()
    > {
    > const Test& ref = Test();
    > cout<< ref<< endl;
    >
    > return EXIT_SUCCESS;
    > }
    >
    > When I compile this program as
    > g++ -std=c++98 -pedantic -Wall -Wextra x.cpp
    >
    > I get the following compilation error:
    > x.cpp: In function `int main()':
    > x.cpp:12: error: `Test::Test(const Test&)' is private
    > x.cpp:33: error: within this context
    >
    > Though the copy ctor of Test is private, the statement
    > const Test& ref = Test();
    > involves only taking a 'const reference' to the temporary Test object
    > created by Test() on the RHS. Since only a reference is made, why does
    > this statement require the copy ctor ?


    It appears to be a bug in the version (3.4.x?) of gcc you are using.

    --
    Ian Collins
     
    Ian Collins, Aug 3, 2010
    #2
    1. Advertising

  3. , India

    Kai-Uwe Bux Guest

    Ian Collins wrote:

    > On 08/ 3/10 04:12 PM, , India wrote:
    >> Consider the following program x.cpp:
    >>

    > <snip>


    Just to be more explicit, I recall the declaration of Test:

    class Test
    {
    public:
    explicit Test(int arg = 10);
    ostream& writeTo(ostream& os) const;
    private:
    Test(const Test& rhs);
    int val;
    };

    Note the private copy constructor.


    >> int main()
    >> {
    >> const Test& ref = Test();
    >> cout<< ref<< endl;
    >>
    >> return EXIT_SUCCESS;
    >> }
    >>
    >> When I compile this program as
    >> g++ -std=c++98 -pedantic -Wall -Wextra x.cpp
    >>
    >> I get the following compilation error:
    >> x.cpp: In function `int main()':
    >> x.cpp:12: error: `Test::Test(const Test&)' is private
    >> x.cpp:33: error: within this context
    >>
    >> Though the copy ctor of Test is private, the statement
    >> const Test& ref = Test();
    >> involves only taking a 'const reference' to the temporary Test object
    >> created by Test() on the RHS. Since only a reference is made, why does
    >> this statement require the copy ctor ?

    >
    > It appears to be a bug in the version (3.4.x?) of gcc you are using.


    It's not a bug. The code is invalid in C++98 and C++03 by [8.5.3/5] which
    requires the copy constructor to be visibile. The compiler is free (but not
    required) to make a copy of the object before initializing the reference.
    The bug is in newer g++ versions (starting with the 4.3 series or
    thereabout).

    The code will be legal in C++0x.


    Best

    Kai-Uwe Bux
     
    Kai-Uwe Bux, Aug 3, 2010
    #3
  4. , India

    Ian Collins Guest

    On 08/ 3/10 06:37 PM, Kai-Uwe Bux wrote:
    > Ian Collins wrote:
    >
    >> On 08/ 3/10 04:12 PM, , India wrote:
    >>> Consider the following program x.cpp:
    >>>

    >> <snip>

    >
    > Just to be more explicit, I recall the declaration of Test:
    >
    > class Test
    > {
    > public:
    > explicit Test(int arg = 10);
    > ostream& writeTo(ostream& os) const;
    > private:
    > Test(const Test& rhs);
    > int val;
    > };
    >
    > Note the private copy constructor.
    >
    >
    >>> int main()
    >>> {
    >>> const Test& ref = Test();
    >>> cout<< ref<< endl;
    >>>
    >>> return EXIT_SUCCESS;
    >>> }
    >>>
    >>> When I compile this program as
    >>> g++ -std=c++98 -pedantic -Wall -Wextra x.cpp
    >>>
    >>> I get the following compilation error:
    >>> x.cpp: In function `int main()':
    >>> x.cpp:12: error: `Test::Test(const Test&)' is private
    >>> x.cpp:33: error: within this context
    >>>
    >>> Though the copy ctor of Test is private, the statement
    >>> const Test& ref = Test();
    >>> involves only taking a 'const reference' to the temporary Test object
    >>> created by Test() on the RHS. Since only a reference is made, why does
    >>> this statement require the copy ctor ?

    >>
    >> It appears to be a bug in the version (3.4.x?) of gcc you are using.

    >
    > It's not a bug. The code is invalid in C++98 and C++03 by [8.5.3/5] which
    > requires the copy constructor to be visibile. The compiler is free (but not
    > required) to make a copy of the object before initializing the reference.
    > The bug is in newer g++ versions (starting with the 4.3 series or
    > thereabout).


    Ah, OK. I missed "The constructor that would be used to make the copy
    shall be callable whether or not the copy is actually done."

    --
    Ian Collins
     
    Ian Collins, Aug 3, 2010
    #4
  5. On 03/08/2010 6.12, , India wrote:
    [...]
    > int main()
    > {
    > const Test& ref = Test();
    > cout<< ref<< endl;
    >
    > return EXIT_SUCCESS;
    > }
    >
    > When I compile this program as
    > g++ -std=c++98 -pedantic -Wall -Wextra x.cpp
    >
    > I get the following compilation error:
    > x.cpp: In function `int main()':
    > x.cpp:12: error: `Test::Test(const Test&)' is private
    > x.cpp:33: error: within this context
    >
    > Though the copy ctor of Test is private, the statement
    > const Test& ref = Test();
    > involves only taking a 'const reference' to the temporary Test object
    > created by Test() on the RHS. Since only a reference is made, why does
    > this statement require the copy ctor ?
    > Kindly clarify, if necessary with a program example.


    I don't know if this is in the FAQ but it should be :) C++98
    required this.

    And although it allowed the copy to be omitted it required the
    copy constructor to be accessible anyway, so that your code
    would not suddenly broke because you switched from a compiler
    that omitted the copy to one that didn't.

    C++0x has a different rule; see core issue 391:

    <http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#391>

    --
    Gennaro Prota | name.surname yahoo.com
    Breeze C++ (preview): <https://sourceforge.net/projects/breeze/>
    Do you need expertise in C++? I'm available.
     
    Gennaro Prota, Aug 3, 2010
    #5
  6. , India

    , India Guest

    * Kai-Uwe Bux <> wrote:
    > Ian Collins wrote:
    > > On 08/ 3/10 04:12 PM, , India wrote:
    > >> Consider the following program x.cpp:

    >
    > > <snip>

    >
    > Just to be more explicit, I recall the declaration of Test:
    >
    > class Test
    > {
    > public:
    > explicit Test(int arg = 10);
    > ostream& writeTo(ostream& os) const;
    > private:
    > Test(const Test& rhs);
    > int val;
    > };
    >
    > Note the private copy constructor.
    >
    >
    >
    > >> int main()
    > >> {
    > >> const Test& ref = Test();
    > >> cout<< ref<< endl;

    >
    > >> return EXIT_SUCCESS;
    > >> }

    >
    > >> When I compile this program as
    > >> g++ -std=c++98 -pedantic -Wall -Wextra x.cpp

    >
    > >> I get the following compilation error:
    > >> x.cpp: In function `int main()':
    > >> x.cpp:12: error: `Test::Test(const Test&)' is private
    > >> x.cpp:33: error: within this context

    >
    > >> Though the copy ctor of Test is private, the statement
    > >> const Test& ref = Test();
    > >> involves only taking a 'const reference' to the temporary Test object
    > >> created by Test() on the RHS. Since only a reference is made, why does
    > >> this statement require the copy ctor ?

    >
    > > It appears to be a bug in the version (3.4.x?) of gcc you are using.

    >
    > It's not a bug. The code is invalid in C++98 and C++03 by [8.5.3/5] which
    > requires the copy constructor to be visibile. The compiler is free (but not
    > required) to make a copy of the object before initializing the reference.
    > The bug is in newer g++ versions (starting with the 4.3 series or
    > thereabout).
    >
    > The code will be legal in C++0x.
    >
    > Best
    >
    > Kai-Uwe Bux


    Thanks for your clarification. In the above program suppose I replace
    the line
    const Test& ref = Test();
    with
    Test obj;
    const Test& ref = obj;
    the program compiles fine. Here is the complete modified program:

    #include <cstdlib>
    #include <iostream>

    using namespace std;

    class Test
    {
    public:
    explicit Test(int arg = 10);
    ostream& writeTo(ostream& os) const;
    private:
    Test(const Test& rhs);
    int val;
    };

    inline Test::Test(int arg) : val(arg)
    {
    cout << "Test one-argument-ctor called" << endl;
    }

    inline ostream& Test::writeTo(ostream& os) const
    {
    return os << val;
    }

    inline ostream& operator<<(ostream& os, const Test& obj)
    {
    return obj.writeTo(os);
    }

    int main()
    {
    Test obj;
    const Test& ref = obj; // note the change here
    cout << ref << endl;

    return EXIT_SUCCESS;
    }

    Suppose I compile this program with g++3.4.3 as
    g++ -std=c++98 -pedantic -Wall -Wextra x.cpp

    it compiles fine and produces the output:
    Test one-argument-ctor called
    10

    My question is why doesn't the compiler allow
    const Test& ref = Test();
    but it allows
    Test obj;
    const Test& ref = obj; // note the change here
    I am unable to understand the difference. Kindly clarify the reason
    regarding how this modified program gets compiled while the earlier
    version doesn't.

    Thanks
    V.Subramanian
     
    , India, Aug 10, 2010
    #6
  7. , India

    SG Guest

    On 10 Aug., 10:01, subramanian10 wrote:
    > * Kai-Uwe Bux wrote:
    > > It's not a bug. The code is invalid in C++98 and C++03 by [8.5.3/5] which
    > > requires the copy constructor to be visibile. The compiler is free (but not
    > > required) to make a copy of the object before initializing the reference.
    > > The bug is in newer g++ versions (starting with the 4.3 series or
    > > thereabout).

    >
    > > The code will be legal in C++0x.

    >
    > Thanks for your clarification. In the above program suppose I replace
    > the line
    >     const Test&  ref = Test();
    > with
    >     Test obj;
    >     const Test&  ref = obj;
    > the program compiles fine.


    [snip]

    > My question is why doesn't the compiler allow
    > const Test& ref = Test();
    > but it allows
    > Test obj;
    > const Test& ref = obj; // note the change here


    For some reason C++98 only requires an object to be copyable if you
    try to initialize a reference with an *rvalue* expression. In your
    case Test() is such an *rvalue* whereas obj is an *lvalue*. Your
    example with 'obj' is really valid C++. As it has already been said,
    this restriction will go away in C++0x. I suppose, that's because none
    of the current compilers actually need to use the copy ctor in both of
    these cases.

    Cheers!
    SG
     
    SG, Aug 10, 2010
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Apricot
    Replies:
    4
    Views:
    530
    velthuijsen
    Apr 16, 2004
  2. NVH
    Replies:
    8
    Views:
    489
    mlimber
    Jul 6, 2006
  3. John Salmon
    Replies:
    3
    Views:
    444
    Victor Bazarov
    Dec 11, 2006
  4. , India

    copy ctor vs default ctor

    , India, Aug 15, 2007, in forum: C++
    Replies:
    2
    Views:
    412
    =?ISO-8859-1?Q?Erik_Wikstr=F6m?=
    Aug 15, 2007
  5. puzzlecracker
    Replies:
    8
    Views:
    431
    James Kanze
    Apr 15, 2008
Loading...

Share This Page