9

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

Leo
  • 497
  • 1
  • 5
  • 12
  • 2
    An anonymous namespace in a header is certainly a wrong design. –  Oct 21 '15 at 19:42
  • 1
    Anonymous namespaces are **intended** to confine scope to the file scope. A named namespace might fit your needs better. – cadaniluk Oct 21 '15 at 19:44
  • 6
    Why not make `PrevCalc` a nested struct of `Calculator`? You won't need to dynamically allocate it then either. – Neil Kirk Oct 21 '15 at 19:44
  • @Dieter Lücking anonymous header is in `.cpp` not in header – Leo Oct 21 '15 at 19:50
  • @Neil Kirk Previously `prev` variables was class members and because of that class was too big. So, if I create nested struct class will remain big. – Leo Oct 21 '15 at 19:54
  • Define "too big"? You can forward-declare a nested struct in the header file and continue to use it dynamically. – Neil Kirk Oct 21 '15 at 19:56
  • @Leo your usage of the forward declaration, which is an declaration in an anonymous namespace in a source file implies the the usage of an anonymous namespace in the header (which you omitted) - Note (!), that will be no good, anyways! –  Oct 21 '15 at 20:00
  • @I have twenty `prev` variables in header and I guess it is not good for reading. However forward declare in header and define in `.cpp` is a good idea – Leo Oct 21 '15 at 20:01
  • @Leo he means that you can put `class PrevCalc;` inside `class Calculator`. This does not affect the size of a Calculator, it only affects the scope of `PrevCalc`. – M.M Oct 21 '15 at 21:00

2 Answers2

6

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;
};
}
Community
  • 1
  • 1
πάντα ῥεῖ
  • 83,259
  • 13
  • 96
  • 175
  • 1
    The problem is, only an anonymous namespace gives you internal linkage. It is pretty sad, there is no way to freely use a completely internal class member (or member function) without hacks. Hope Modules will improve that! At least we'll have module-internal classes and whatnot. – user362515 Jan 25 '16 at 11:38
1

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(){}
Mizux
  • 3,747
  • 2
  • 17
  • 27