POV-Ray : Newsgroups : povray.off-topic : C++ question Server Time
28 Jul 2024 18:25:05 EDT (-0400)
  C++ question (Message 1 to 10 of 15)  
Goto Latest 10 Messages Next 5 Messages >>>
From: Anthony D  Baye
Subject: C++ question
Date: 3 Oct 2013 04:15:01
Message: <web.524d26607f0c475f328783aa0@news.povray.org>
I'm working on what is probably a complicated solution to a relatively trivial
problem.  I have no idea whether I'm doing this right or not (well, obviously,
I'm doing -something- wrong) but based on everything I've read, and all of the
examples I could dig up, I don't see anything wrong with my structure.

basically, I have a custom library:

#ifndef _MY_LIB_
#define _MY_LIB_
#include <iostream>
#include <cmath>
using std::ostream;

namespace geometry {

    enum pointName{X,Y,Z};

    class point3d
    {
        public:
        .
        .
        .
        friend ostream &operator <<(ostream &, const point3d &);

        private:
    };

    class vector3d : public point3d
    {
        ...
    };

    const point3d ORIGIN;
    const vector3d ZERO_VECTOR;
}

class implementations are handled in separate files, and compiled with:

g++ -g -c -Wall -std=c++0x point3d.cpp vector3d.cpp

This compiles fine, and everything is awesome until I try to use the << operator
in my unit test program.  g++ gives me the following:

g++ -g -Wall -o uTest unit_test.cpp point3d.o vector3d.o
/tmp/cca86ida.o: In function `point_arithmetic_test()':
/home/.../Documents/Projects/Planets/unit_test.cpp:56:
undefined reference to `geometry::operator<<(std::basic_ostream<char,
std::char_traits<char> >&, geometry::point3d const&)'
/home/.../Documents/Projects/Planets/unit_test.cpp:57:
undefined reference to `geometry::operator<<(std::basic_ostream<char,
std::char_traits<char> >&, geometry::point3d const&)'
collect2: ld returned 1 exit status
make: *** [uTest] Error 1

now unit_test.cpp, like both of my library files uses:

using namespace geometry;

if I remove the namespace wrapper from around my classes, everything works.

can somebody tell me what I'm missing?

Regards,
A.D.B.


Post a reply to this message

From: Anthony D  Baye
Subject: Re: C++ question
Date: 3 Oct 2013 04:25:00
Message: <web.524d28c61cbd09d0328783aa0@news.povray.org>
"Anthony D. Baye" <Sha### [at] spamnomorehotmailcom> wrote:
> I'm working on what is probably a complicated solution to a relatively trivial
> problem.  I have no idea whether I'm doing this right or not (well, obviously,
> I'm doing -something- wrong) but based on everything I've read, and all of the
> examples I could dig up, I don't see anything wrong with my structure.
>
> basically, I have a custom library:
>
> #ifndef _MY_LIB_
> #define _MY_LIB_
> #include <iostream>
> #include <cmath>
> using std::ostream;
>
> namespace geometry {
>
>     enum pointName{X,Y,Z};
>
>     class point3d
>     {
>         public:
>         .
>         .
>         .
>         friend ostream &operator <<(ostream &, const point3d &);
>
>         private:
>     };
>
>     class vector3d : public point3d
>     {
>         ...
>     };
>
>     const point3d ORIGIN;
>     const vector3d ZERO_VECTOR;
> }
>
> class implementations are handled in separate files, and compiled with:
>
> g++ -g -c -Wall -std=c++0x point3d.cpp vector3d.cpp
>
> This compiles fine, and everything is awesome until I try to use the << operator
> in my unit test program.  g++ gives me the following:
>
> g++ -g -Wall -o uTest unit_test.cpp point3d.o vector3d.o
> /tmp/cca86ida.o: In function `point_arithmetic_test()':
> /home/.../Documents/Projects/Planets/unit_test.cpp:56:
> undefined reference to `geometry::operator<<(std::basic_ostream<char,
> std::char_traits<char> >&, geometry::point3d const&)'
> /home/.../Documents/Projects/Planets/unit_test.cpp:57:
> undefined reference to `geometry::operator<<(std::basic_ostream<char,
> std::char_traits<char> >&, geometry::point3d const&)'
> collect2: ld returned 1 exit status
> make: *** [uTest] Error 1
>
> now unit_test.cpp, like both of my library files uses:

I forgot to type the #endif after the namespace in my example... It is there in
the real thing.
>
> using namespace geometry;
>
> if I remove the namespace wrapper from around my classes, everything works.
>
> can somebody tell me what I'm missing?
>
> Regards,
> A.D.B.


Post a reply to this message

From: Le Forgeron
Subject: Re: C++ question
Date: 3 Oct 2013 12:22:43
Message: <524d99d3@news.povray.org>
Le 03/10/2013 10:14, Anthony D. Baye nous fit lire :
> I'm working on what is probably a complicated solution to a relatively trivial
> problem.  I have no idea whether I'm doing this right or not (well, obviously,
> I'm doing -something- wrong) but based on everything I've read, and all of the
> examples I could dig up, I don't see anything wrong with my structure.
> 
> basically, I have a custom library:
> 
> #ifndef _MY_LIB_
> #define _MY_LIB_
> #include <iostream>
> #include <cmath>
> using std::ostream;
> 
> namespace geometry {
> 
>     enum pointName{X,Y,Z};
> 
>     class point3d
>     {
>         public:
>         .
>         .
>         .
>         friend ostream &operator <<(ostream &, const point3d &);
> 
>         private:
>     };
> 
>     class vector3d : public point3d
>     {
>         ...
>     };
> 
>     const point3d ORIGIN;
>     const vector3d ZERO_VECTOR;
> }
> 
> class implementations are handled in separate files, and compiled with:
> 
> g++ -g -c -Wall -std=c++0x point3d.cpp vector3d.cpp
> 
> This compiles fine, and everything is awesome until I try to use the << operator
> in my unit test program.  g++ gives me the following:
> 
> g++ -g -Wall -o uTest unit_test.cpp point3d.o vector3d.o
> /tmp/cca86ida.o: In function `point_arithmetic_test()':
> /home/.../Documents/Projects/Planets/unit_test.cpp:56:
> undefined reference to `geometry::operator<<(std::basic_ostream<char,
> std::char_traits<char> >&, geometry::point3d const&)'
> /home/.../Documents/Projects/Planets/unit_test.cpp:57:
> undefined reference to `geometry::operator<<(std::basic_ostream<char,
> std::char_traits<char> >&, geometry::point3d const&)'
> collect2: ld returned 1 exit status
> make: *** [uTest] Error 1
> 
> now unit_test.cpp, like both of my library files uses:
> 
> using namespace geometry;
> 
> if I remove the namespace wrapper from around my classes, everything works.
> 
> can somebody tell me what I'm missing?
> 
you declared a friend function <<, but did you provide its
implementation in some cpp file ? (with accurate namespace matching ?)

reminder: that's a class-free function (not member of point3d), and you
are allowed to implement a function without declaring it first, so it
could happen that your implementation is not matching the signature
declared in the header file without generating an error.

Otherwise, avoid "using std::ostream", and have explicit:
         friend std::ostream &operator <<(std::ostream &, const point3d &);


You might want to replace <iostream> (heavy) with <iosfwd> in the header
files, reserving iostream to the source files that actually need streams
usage.


Post a reply to this message

From: Warp
Subject: Re: C++ question
Date: 3 Oct 2013 13:15:49
Message: <524da645@news.povray.org>
Anthony D. Baye <Sha### [at] spamnomorehotmailcom> wrote:
> undefined reference to `geometry::operator<<(std::basic_ostream<char,

You have declared that function, but apparently you have not
implemented it anywhere, therefore the linker cannot find it when
you try to use it.

>         friend ostream &operator <<(ostream &, const point3d &);

Ostensibly that function will probably not need anything from your
class that isn't readable through its public interface. It's of course
not wrong, but it would be better to avoid making it a friend function
unless there's a good reason for that.

Just declare it as a function inside your 'geometry' namespace
(and then implement it somewhere, of course.)

-- 
                                                          - Warp


Post a reply to this message

From: Anthony D  Baye
Subject: Re: C++ question
Date: 3 Oct 2013 14:45:00
Message: <web.524dba121cbd09d0328783aa0@news.povray.org>
Warp <war### [at] tagpovrayorg> wrote:
> Anthony D. Baye <Sha### [at] spamnomorehotmailcom> wrote:
> > undefined reference to `geometry::operator<<(std::basic_ostream<char,
>
> You have declared that function, but apparently you have not
> implemented it anywhere, therefore the linker cannot find it when
> you try to use it.
>
> >         friend ostream &operator <<(ostream &, const point3d &);
>
> Ostensibly that function will probably not need anything from your
> class that isn't readable through its public interface. It's of course
> not wrong, but it would be better to avoid making it a friend function
> unless there's a good reason for that.
>
> Just declare it as a function inside your 'geometry' namespace
> (and then implement it somewhere, of course.)
>
> --
>                                                           - Warp

I also tried declaring it as a class function:

ostream &operator <<(ostream &);

not realizing, of course that it couldn't be used like it should be... but
-every- example I could find for how to overload the operator properly
(Admittedly, without looking at my textbooks) showed it as a friend.  And it
works that way, but only if the class isn't part of a namespace, which is what
I'm trying to understand...

And while it's true that it wouldn't require anything not available from the
public interface, having it as a friend function allows it to access the private
data members directly without having to resort to a function call.

....

Before replying, I tried moving the declaration to the bottom of the namespace
as an inline function, rather than defining it in point3d.cpp as I had been
doing, but I get the same result when I try to compile uTest.

I'm including my source as a zip file.

Regards,
A.D.B.


Post a reply to this message


Attachments:
Download 'geometry.zip' (4 KB)

From: Anthony D  Baye
Subject: Re: C++ question
Date: 3 Oct 2013 14:50:01
Message: <web.524dbba81cbd09d0328783aa0@news.povray.org>
I forgot to uncomment the function definition in point3d.cpp before I
uploaded...

and I made a stupid in my comment:  I forgot that friend functions can access
protected members, but not private members, so you were right that it would be
better off as a free function within the namespace, but it still doesn't work
right when I compile uTest.

Regards,
A.D.B.


Post a reply to this message

From: Le Forgeron
Subject: Re: C++ question
Date: 3 Oct 2013 15:20:15
Message: <524dc36f@news.povray.org>
Le 03/10/2013 20:47, Anthony D. Baye nous fit lire :
> I forgot to uncomment the function definition in point3d.cpp before I
> uploaded...
> 
> and I made a stupid in my comment:  I forgot that friend functions can access
> protected members, but not private members, so you were right that it would be
> better off as a free function within the namespace, but it still doesn't work
> right when I compile uTest.

the operator<< must be implemented in geometry namespace, and friend is
not enough to declare a function.

Enjoy.

diff -r 9b234d20a210 -r 1840dc7961c9 geometry.h
--- a/geometry.h        Thu Oct 03 21:18:39 2013 +0200
+++ b/geometry.h        Thu Oct 03 21:17:32 2013 +0200
@@ -28,6 +28,7 @@
     private:
         double coords[3];
     };
+               ostream &operator <<(ostream &, const point3d &);

     // 3D geometric vector class extends point3d through inheritance.
     // Angles are measured in radians.
diff -r 9b234d20a210 -r 1840dc7961c9 point3d.cpp
--- a/point3d.cpp       Thu Oct 03 21:18:39 2013 +0200
+++ b/point3d.cpp       Thu Oct 03 21:17:32 2013 +0200
@@ -62,9 +62,9 @@
 //    return os;
 //}

-//ostream &operator <<(ostream &os, const point3d &P)
-//{
-//    os << "(" << P.coords[X] << ", " << P.coords[Y] << ", " <<
P.coords[Z] << ")" << endl;
+ostream & geometry::operator <<(ostream &os, const point3d &P)
+{
+    os << "(" << P.coords[X] << ", " << P.coords[Y] << ", " <<
P.coords[Z] << ")" << endl;

-//    return os;
-//}
+    return os;
+}


Post a reply to this message

From: Le Forgeron
Subject: Re: C++ question
Date: 3 Oct 2013 15:22:33
Message: <524dc3f9@news.povray.org>
Le 03/10/2013 21:20, Le_Forgeron nous fit lire :
>  I forgot that friend functions can access
>> protected members, but not private members, 

Hummm... friend can access private. There is no reserved intimacy for
friend.


Post a reply to this message

From: Warp
Subject: Re: C++ question
Date: 3 Oct 2013 15:41:58
Message: <524dc886@news.povray.org>
Anthony D. Baye <Sha### [at] spamnomorehotmailcom> wrote:
> I also tried declaring it as a class function:

This works just fine:

//----------------------------------------------------------------------
#include <iostream>

namespace geometry
{
    class A
    {
     public:
        int value() const { return 5; }
    };

    inline std::ostream& operator<<(std::ostream& os, const A& obj)
    {
        os << obj.value();
        return os;
    }
}

int main()
{
    geometry::A a;
    std::cout << a << std::endl;
}
//----------------------------------------------------------------------


-- 
                                                          - Warp


Post a reply to this message

From: Anthony D  Baye
Subject: Re: C++ question
Date: 3 Oct 2013 16:00:01
Message: <web.524dccb71cbd09d0328783aa0@news.povray.org>
Le_Forgeron <jgr### [at] freefr> wrote:
> Le 03/10/2013 21:20, Le_Forgeron nous fit lire :
> >  I forgot that friend functions can access
> >> protected members, but not private members,
>
> Hummm... friend can access private. There is no reserved intimacy for
> friend.

Not according to the test I did about an hour ago.  I declared the function as a
friend in point3d and defined it in point3d.cpp, and got told off by g++ for
attempting to access point3d's private members.

At any rate, defining it as warp mentioned using the inline keyword seems to
work, but according to what I've read, that just gives the compiler a hint that
it can be copied in wherever it's called rather than being called as a function.
 I suppose that it won't affect the size of my program all that much, but if I'd
wanted it done that way, I could write it that way. (of course, I understand
that typing a function call is easier than copying a chunk of code several
times)

Anyway, the program compiles now, I just wish I could find out why it was being
so stubborn with the friend function of a class contained in a namespace.

Thanks for the assist.

Regards,
A.D.B


Post a reply to this message

Goto Latest 10 Messages Next 5 Messages >>>

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.