views:

632

answers:

4

Hi all! I have a situaion in which I want to declare a class member function returning a type that depends on the class itself. Let me give you an example:

class Substring {
    private:
        string the_substring_;
    public:
        // (...)
        static SubstringTree getAllSubstring(string main_string, int min_size);
};

And SubstringTree is defined as follows:

typedef set<Substring, Substring::Comparator> SubstringTree;

My problem is that if I put the SubstringTree definition after the Substring definition, the static method says it doesn't know SubstringTree. If I reverse the declarations, then the typedef says it doesn't know Substring.

How can I do it? Thanks in advance.

+5  A: 

You could define it inside the class:

class Substring {
    private:
        string the_substring_;
    public:
        // (...)
        typedef set<Substring, Substring::Comparator> SubstringTree;
        static SubstringTree getAllSubstring(string main_string, int min_size);
};
Bojan Resnik
But then you have to refer to it with `Substring::SubstringTree`
Zifre
... which may not be a bad idea at all. It would help declutter the global namespace. I'd even go with Substring::Tree.
Ates Goral
But then you can add another typedef outside the class that redefines it in the global scope
shoosh
@Ates Goral: Yes, I think `Substring::Tree` would actually be the best solution, but `Substring::SubstringTree` is sort of redundant.
Zifre
I'll go with Substring::Tree. Thanks!
Rafael Almeida
Cluttering the global namespace should be avoided, if possible. I agree that the type should be renamed to `Substring::Tree` though.
Bojan Resnik
+2  A: 

You can predeclare a class with this:

class Foo;

Keep in mind that before the class is actually defined, you can only declare pointers to it, not instances.

Zifre
Typical circular inclusion.
dborba
A: 

forward declaration

class Substring;

I don't know if that will work for non pointer uses of Substring though.

Ben Hughes
It doesn't, in general.
David Thornley
+5  A: 

As you've written it, the short answer is you can't.

You do have a few close alternatives:

1) Declare SubstringTree in Substring

class Substring {
public:
    class Comparator;
    typedef set< Substring, Comparator> Tree;

private:
    string the_substring_;
public:
    // (...)
    static Tree getAllSubstring(string main_string, int min_size);
};

typedef Substring::Tree SubstringTree;

2) Define the Comparator outside of Substring:

class Substring;
class SubstringComparator;
typedef set< Substring, SubstringComparator> SubstringTree;

class Substring {
public:

private:
    string the_substring_;
public:
    // (...)
    static SubstringTree getAllSubstring(string main_string, int min_size);
};

3) You can use a template to delay the lookup until you have more declarations:

template <typename String>
struct TreeHelper
{
  typedef set< String, typename String::Comparator> Tree;
};

class Substring {
public:
  class Comparator;

private:
  string the_substring_;
public:
  // (...)
  static TreeHelper<Substring>::Tree getAllSubstring(string main_string
                                             , int min_size);
};

typedef TreeHelper<Substring>::Tree SubstringTree;
Richard Corden