jvpernis
jvpernis

Reputation: 205

Defining unnamed class member functions?

I currently have two unnamed classes defined in my Foo.h:

class Foo {
public:
    Foo();

    class {
    private:
        int x;
        int y;
    public:
        int GetX() { return x; }
        int GetY() { return y; }
    } Sub1;

    class {
    private:
        int x;
    public:
        int GetX() { return x; }
    } Sub2;
}

This code compiles just fine, and it used like this:

 Foo temp;
 int Ax, Ay, Bx;
 Ax = temp.Sub1.GetX();
 Ay = temp.Sub1.GetY();
 Bx = temp.Sub2.GetX();

However, now I want to move the member function definitions to the source file.The only way I know to split this class into a header file and source file, is to name the classes:

Foo.h:

class Foo {

private:    
    class A {
    private:
        int x;
        int y;
    public:
        int GetX();
        int GetY();
    };

    class B {
    private:
        int x;
    public:
        int GetX();
    };

public:
    Foo();
    A Sub1;
    B Sub2;

}

Foo.cpp:

int Foo::A::GetX() { return x; }
int Foo::A::GetY() { return y; }
int Foo::B::GetX() { return x; }

This code is not what I want, however, since it is ugly and I didn't want a named class in the first place.

Is it possible to split the class into a header file and source file? Or is this just bad code design?

Upvotes: 6

Views: 656

Answers (2)

Kai Petzke
Kai Petzke

Reputation: 2934

With gcc at least, you can do the trick using decltype:

int decltype(Foo::Sub1)::GetX() { return x; }

It is not standards compliant, though, as Columbo has already pointed out. So don't blame me, if a future version of gcc refuses to compile this. But we all now, that gcc has never been dogmatic about standards compliance, and that the gcc team has a strong tendency to keep language extensions, if they are both unambigous (which is clearly the case here) and useful to at least some programmers. Over the time, many of these gcc extensions have eventually become part of the standards.

Nonetheless, clang and probably most other compilers refuse this construct with the error message:

'decltype' cannot be used to name a declaration

But even clang can be tricked into accepting the decltype trick. We just need to do a typedef:

typedef decltype(Foo::Sub1) Sub1type;
int Sub1type::GetX() { return x; }

Of course, this is not much different to naming the unnamed classes. The advantage of the typedef solution might still be, that you can hide away the type names inside a private namespace.

Upvotes: 1

Columbo
Columbo

Reputation: 60969

It is, unfortunately, impossible. §9.3/5:

If the definition of a member function is lexically outside its class definition, the member function name shall be qualified by its class name using the :: operator.

Since no class name exists, no out-of-class definitions for member functions are possible. The fact that GCC allows decltype-specifiers in this context is a bug.

Upvotes: 3

Related Questions