Archived

This topic is now archived and is closed to further replies.

Namespaces and friend functions

This topic is 5984 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Ok, given that I make a lot of data types that I want to use in STL containers, it makes sense for me to write a specialisation of the std::swap function. std::swap gets used a lot when sorting or reordering containers. The default std::swap looks something like this:
void swap(T& t1, T& t2)
{
    T temp(t2);
    t1 = t2;
    t2 = temp;
} 
This is adequate for most needs, but quite often you have a class which contains mostly pointers to data. Therefore you can write a much more efficient version of std::swap for your own types just by swapping pointers rather than using whole assignments which involve copying all the data that is pointed to. (Assuming you wrote a decent operator= function. This is an example of where doing 1 thing the right way actually makes things harder for you in others!) Now, most such specialised swap functions will need access to private or protected data members. This means they need to be a friend function. Also, the swap function is meant to be a specialisation of std::swap, therefore it should be in the std namespace. Otherwise the default version could be called when I actually wanted my specialised version. The problem is, I can''t quite work out how to do this properly. If I use this code: // in MyClass header friend void swap(MyClass& x, MyClass& y); // in MyClass cpp namespace std { void swap(MyClass& x, MyClass& y) { ...etc... I get the error "cannot access private member." Because the friend function is referring to swap, and the function I made is actually std::swap. If I change the line in the header file to: friend void std::swap(MyClass& x, MyClass& y); I get the error "''std'' : is not a class or namespace name". If I change the line in the header file to: namespace std { friend void swap(String& x, String& y); } I get this error: "syntax error : ''namespace''". So. What is the answer? I need my function in std:: and I need it to have access to private members to work properly.

Share this post


Link to post
Share on other sites
No. If I do that, then it says that ''swap is not a member of std''. If I then #include something like <algorithm> to convince it of this fact, it says "''swap'' : unable to resolve function overload". And that''s without even getting as far as deciding whether it can access private members or not.

Share this post


Link to post
Share on other sites
As it happens, I got around my own problem by defining a public member function called swap, and had the std::swap call that one. This seems to be what is needed. But it doesn''t solve the original problem as such (if it is even solvable), being the friend/namespace conflict.

Share this post


Link to post
Share on other sites
If you want a specialization of swap, I think you are doing it the wrong way.


    
// In Header.h - Class header

#pragma once
#include <algorithm>

class C
{
// THIS DOES NOT COMPILE WITH VC++ 6

template <class T> friend void std::swap(T &, T &);
public:
C() {}
~C() {}
private:
void F() {};
};

namespace std
{
template <> void swap<C>( C &c, C &d )
{
c.F(); // call private function

}
}



Provide a full specialization of std::swap. This doesn't not compile with VC++ 6 because there are some problems with friend templates with VC, but I think the syntax should be correct

I'm at work now and have no access to other compilers, I will check later when I get home.



Edited by - void on July 29, 2001 11:57:19 PM

Share this post


Link to post
Share on other sites
Keep in mind the reason that swap works the way it does is to remain exception-safe. At no point during the swap should any objects be in an inconsistant state should an exception occur. I don''t know what your particular efficiency improvement is, but just take care that it doesn''t compromise safety. Once you start down the dark path, forever will it dominate your destiny.

Share this post


Link to post
Share on other sites
Checked it with g++ 2.95. It compiles fine.

However, I should also let you know it is generally not advisable to add things to the std namespace. But if you got a good reason, go ahead.

Share this post


Link to post
Share on other sites