Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gcc failes to compile operator definition with prefixed namespace

I have operators declared for class my_type in namespace my_namespace.

namespace my_namespace {
 class my_type
 {
  friend std::ostream& operator << (std::ostream& out, my_type t);
 }
}

I'm trying to define these operators in implementation file, but when I write something like that

std::ostream& my_namespace::operator << (std::ostream& out, my_type t)
{
 out << t;
 return out;
}

I get error message

error: ... operator should have been declared inside 'my_namespace'

When I change it to

namespace my_namespace {
    std::ostream& operator << (std::ostream& out, my_type t)
    {
     out << t;
     return out;
    }
}

then it's compiles, but I don't understand the problem. Why does this failed to compile? Is there everything right with that? I would appreciate link to standard as I really don't know what to search.

added

file.h

#ifndef A_H
#define A_H

#include <iosfwd>

namespace N
{
 class A
 {
  friend std::ostream& operator << (std::ostream& out, A& obj);
 };
}

#endif

file.cpp

#include "file.h"
#include <iostream>

std::ostream& N::operator << (std::ostream& out, N::A& obj)
{
 return out;
}

int main() {}

here is complete example. This works fine on VS2010, but gives above mentioned error on gcc 4.4.5.

added

hmm...yes, this one works

namespace N
{
    class A
    {
        friend std::ostream& operator << (std::ostream& out, A& obj);
    };
    std::ostream& operator << (std::ostream& out, A& obj);
}

I was always thinking that in terms of visibility declaring friend operator in class is same thing as declaring outside of the class..looks like it's not. Thanks.

Thanks much in advance.

like image 794
ledokol Avatar asked Jan 21 '11 10:01

ledokol


2 Answers

The error message says it all, actually. You can keep your function definition in the implementation file, but you need to declare it in the namespace first:

namespace my_namespace {
    std::ostream& operator << (std::ostream& out, my_type t);
}

The C++ standard is quite clear about this:

7.3.1.2/3:

Every name first declared in a namespace is a member of that namespace. If a friend declaration in a non-local class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. The name of the friend is not found by simple name lookup until a matching declaration is provided in that namespace scope (either before or after the class declaration granting friendship). If a friend function is called, its name may be found by the name lookup that considers functions from namespaces and classes associated with the types of the function arguments (3.4.2). When looking for a prior declaration of a class or a function declared as a friend, and when the name of the friend class or function is neither a qualified name nor a template-id, scopes outside the innermost enclosing namespace scope are not considered. .

The following link puts it more simply, and adds a few examples: http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/cplr043.htm

So I'd say that gcc is wrong here.. The relevant sentence seems to be "The name of the friend is not found by simple name lookup until a matching declaration is provided in that namespace scope (either before or after the class declaration granting friendship).

like image 61
Daniel Gehriger Avatar answered Nov 14 '22 14:11

Daniel Gehriger


Declarations refer to a set of other names, and introduce a single new name; this new name must not be qualified with a namespace identifier, but rather the declaration needs to be inside the namespace block in which the new name should be declared.

The same rules apply to definitions, as they imply a declaration. The friend declaration is special, because it lives inside another definition and doesn't really declare anything.

like image 1
Simon Richter Avatar answered Nov 14 '22 12:11

Simon Richter