2
struct AAA;
struct CCC;

struct AAA
{
    struct BBB
    {
    };
    CCC::DDD* Return()
    {
        return nullptr;
    }
};

struct CCC
{
    struct DDD
    {
    };
    AAA::BBB* Return()
    {
        return nullptr;
    }
};

I tried struct AAA::BBB, struct CCC::DDD, but I couldn't get it to compile no matter what I did. thx!

john
  • 85,011
  • 4
  • 57
  • 81
Hooaasin
  • 23
  • 3
  • 1
    Voted to reopen, the suggested dupe does not cover the situation here, which concerns nested classes. AFAIK there is no solution to the OPs problem but maybe someone else can confirm or refute that, – john Aug 15 '23 at 05:37
  • 2
    Check this question: https://stackoverflow.com/questions/1021793/how-do-i-forward-declare-an-inner-class – Özgür Murat Sağdıçoğlu Aug 15 '23 at 05:39
  • 2
    @ÖzgürMuratSağdıçoğlu The dupe of that question does seem to be a dupe of this question, and it confirms what I thought, there is no solution to this exact problem in C++. – john Aug 15 '23 at 05:49
  • 2
    OK I was wrong. In C++14 there is a solution, declare the return type as `auto`. Whether that generalises to the OP's real code is another question, but it is an answer to the code posted here. – john Aug 15 '23 at 06:04
  • 2
    @john samely you may solve that with templated code. That's as long as definitions do not use each other, Koenig help you if you try that. – Swift - Friday Pie Aug 15 '23 at 06:08

2 Answers2

3

In C++14, you don't need to forward declare these classes, just declare the return type of AAA::Return() as auto and define it later

struct AAA
{
    struct BBB
    {
    };
    auto Return();
};

struct CCC
{
    struct DDD
    {
    };
    AAA::BBB* Return()
    {
        return nullptr;
    }
};

auto AAA::Return()
{
  return static_cast<CCC::DDD*>(nullptr);
}
康桓瑋
  • 33,481
  • 5
  • 40
  • 90
  • 3
    Should be noted, that like with templates, the definition of `AAA::Return()` here should be visible before its use. It's somewhat a cross between template and a generic. – Swift - Friday Pie Aug 15 '23 at 06:05
1

I have been inspired by @Swift - Friday Pie to code up a template based solution. It's a use of templates I'd never considered before. Here it is

#include <iostream>

template <int N>
struct CCC_temp;

template <int N>
struct AAA_temp
{
    struct BBB
    {
    };
    typename CCC_temp<N>::DDD* Return()
    {
        return nullptr;
    }
};

template <int N>
struct CCC_temp
{
    struct DDD
    {
    };
    typename AAA_temp<N>::BBB* Return()
    {
        return nullptr;
    }
};

using AAA = AAA_temp<0>;
using CCC = CCC_temp<0>;

int main()
{
    AAA a;
    std::cout << a.Return() << '\n';
}

I think I prefer it to the auto return solution. It's a bit more long-winded, but a bit more general too.

Note - use of typename is apparently optional (my compiler doesn't object if they are removed) but I get a little confused about exactly when typename is required and when it is not, so I left them in.

john
  • 85,011
  • 4
  • 57
  • 81