Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to forward declare class which is in unnamed namespace

Tags:

c++

I am trying to create class with lazy calculations. So I need struct to hold previously calculated variables and I want to put that class into unnamed namespace(don't want to pollute global scope). Here is minimal code which explains what I want: calculator.h:

#ifndef CALCULATOR_H
#define CALCULATOR_H

class PrevCalc;
class Calculator
{
public:
    Calculator();
    PrevCalc* prevCalc;
};

#endif // CALCULATOR_H

calculator.cpp:

#include "calculator.h"
namespace{
    struct PrevCalc{
        double prevA = -1;
        double prevB = -1;
        double prevC = -1;
    };
}
Calculator::Calculator()
{
    prevCalc = new PrevCalc();
}

Of course it gives an error expected type-specifier before 'PrevCalc' and if I define PrevCalc without namespace everything works fine. My question is how to declare class which will be defined in unnamed namespace in .cpp file

like image 406
Leo Avatar asked Oct 21 '15 19:10

Leo


2 Answers

You could also use a nested class ?

#ifndef CALCULATOR_H
#define CALCULATOR_H

class Calculator {
public:
    Calculator();
    ~Calculator(); // need an explicit destructor to use std::unique_ptr<>
private:
    struct PrevCalc;
    std::unique_ptr<PrevCalc> prevCalc;
};

#endif // CALCULATOR_H

in .cc file

#include "calculator.h"

struct Calculator::PrevCalc{
  double prevA = -1;
  double prevB = -1;
  double prevC = -1;
};

Calculator::Calculator():
  prevCalc(std::make_unique<PrevCalc>())
{}

Calculator::~Calculator(){}
like image 80
Mizux Avatar answered Sep 17 '22 00:09

Mizux


My question is how to declare class which will be defined in unnamed namespace in .cpp file

You cannot. The unnamed namespace is explicitly meant to be privately visible for the current translation unit it appears in, and cannot be used for forward declarations inherently.

You're probably be better off using the pimpl idiom, if you want to hide implementation details.


Another popular approach is using an internal_ namespace, and document it's not meant for public usage:

namespace calculators {
namespace internal_ {
    struct PrevCalc{
        double prevA = -1;
        double prevB = -1;
        double prevC = -1;
    };
}

class Calculator {
public:
    Calculator();
private: // !!!!
    internal_::PrevCalc* prevCalc;
};
}
like image 21
πάντα ῥεῖ Avatar answered Sep 19 '22 00:09

πάντα ῥεῖ