Bjarke Hammersholt Roune
2011-06-04 07:40:24 UTC
Summary: Should I, and if so how, move private member functions out of
header files when they refer to a private inner class?
Consider this code, where I'd like to move implementationDetail(int)
to the implementation file:
class Outer {
public:
// ...
private:
int implementationDetail(int v);
struct Inner {
// ...
};
vector<Inner> v;
};
Here implementationDetail is something that someone who wants to use
the interface of Outer doesn't need to know about, so it is private.
Unfortunately, it is still there in the header file and if I change
the signature of implementationDetail, that will trigger a
recompilation of files that include Outer's header file. If
implementationDetail only refers to few member variables I therefore
prefer to move its declaration out of the header file and instead make
it a free-standing function in the implementation file. Something like
this:
// in implementation file
namespace {
int implementationDetail(int v) {return v + 1;}
}
This way header files get smaller, there will be fewer recompilations
and someone (e.g. me in a week) reading my header file to get its
interface will have less stuff to mentally tune out. So far so good.
However, this cannot be done if implementationDetail takes an Inner:
// in implementation file
namespace {
// error: Outer::Inner is private
int implementationDetail(Outer::Inner inner) {
return inner.a + inner.b;
}
}
The problem is that Inner is private. This can sometimes be solved by
moving Inner into the implementation file just as we did for
implementationDetail. This won't work here because we can't have a
vector<Inner> member then - it would work if we had an Inner* member
instead. So inner private classes defeat moving implementation details
out of header files in this way.
What's the best practice here? One way is to declare defeat and just
leave implementationDetail in the header file, though I'm not too
happy about that.
Now I do have a work-around that technically works, but I don't like
it much. You can do it this way:
// in implementation file
namespace {
template<class TemplateInner>
int implementationDetail(TemplateInner inner) {
return inner.a + inner.b;
}
}
If you pass a private class as a template parameter to a function then
that function gains access to the class even if it is private. So if
you call implementationDetail with an Outer::Inner as a parameter,
this code will do the right thing, but it's really not pretty. Is
there a better way?
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
header files when they refer to a private inner class?
Consider this code, where I'd like to move implementationDetail(int)
to the implementation file:
class Outer {
public:
// ...
private:
int implementationDetail(int v);
struct Inner {
// ...
};
vector<Inner> v;
};
Here implementationDetail is something that someone who wants to use
the interface of Outer doesn't need to know about, so it is private.
Unfortunately, it is still there in the header file and if I change
the signature of implementationDetail, that will trigger a
recompilation of files that include Outer's header file. If
implementationDetail only refers to few member variables I therefore
prefer to move its declaration out of the header file and instead make
it a free-standing function in the implementation file. Something like
this:
// in implementation file
namespace {
int implementationDetail(int v) {return v + 1;}
}
This way header files get smaller, there will be fewer recompilations
and someone (e.g. me in a week) reading my header file to get its
interface will have less stuff to mentally tune out. So far so good.
However, this cannot be done if implementationDetail takes an Inner:
// in implementation file
namespace {
// error: Outer::Inner is private
int implementationDetail(Outer::Inner inner) {
return inner.a + inner.b;
}
}
The problem is that Inner is private. This can sometimes be solved by
moving Inner into the implementation file just as we did for
implementationDetail. This won't work here because we can't have a
vector<Inner> member then - it would work if we had an Inner* member
instead. So inner private classes defeat moving implementation details
out of header files in this way.
What's the best practice here? One way is to declare defeat and just
leave implementationDetail in the header file, though I'm not too
happy about that.
Now I do have a work-around that technically works, but I don't like
it much. You can do it this way:
// in implementation file
namespace {
template<class TemplateInner>
int implementationDetail(TemplateInner inner) {
return inner.a + inner.b;
}
}
If you pass a private class as a template parameter to a function then
that function gains access to the class even if it is private. So if
you call implementationDetail with an Outer::Inner as a parameter,
this code will do the right thing, but it's really not pretty. Is
there a better way?
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]