Re: Why is the definition of a member function required to be in
the same namespace as its class?
[Got rejected once.]
On Wednesday, September 25, 2013 9:50:02 AM UTC-4, plash wrote:
To avoid having to write an obscene number of definitions for each
deriving class in this codebase, I have created an implementation
stub as a class template and am defining the actual functions based
on a type enum.
[SNIP]
Here's an example of what I'm up to:
namespace A {
enum class Type : unsigned { SomeType, /*...*/ }
class Base { protected: virtual void f() = 0; /*...*/ };
template<Type type, class Data>
class Impl final : public Base
{ private: void f() override; /*...*/ };
} // namespace A
namespace B {
struct SomeTypeData { /* POD or standard-layout */ };
void A::Impl<Type::SomeType, SomeTypeData> f() { /*...*/ }
} // namespace B
AFAIK, you can't specialize a method just for one version of a class
template. You have to specialize (or partially specialize) the class
template and recreate the members, copying the definitions or altering
them as desired. (You can even add, remove, or severely-alter members.
But as std::vector<bool> has shown, that will wreck havoc as far as
generic substitutability is concerned.) Maybe a secret implementation
base class can help from repeating code.
* Remove that bad version of "f."
* After the "namespace B" block, make a new "namespace A" block.
* Declare a class template specialization of "Impl," with "SomeType"
and "SomeTypeData" as the parameters. Derive from "Base" and
otherwise copy the original version of the template. Alter that
version of "f" as you want.
There's probably a better solution, with more generality and
indirection, but I'll let someone else handle that.
....
What about:
namespace A {
enum class Type : unsigned;
template < Type type, class Data >
struct f_action;
class Base
{
public:
void call_f() { f(); }
virtual ~Base() = default;
private:
virtual void f() = 0;
}
template < Type type, class Data >
class Impl final
: public Base
{
public:
Impl( Data d ) : m_data( std::move(d) ) {}
private:
Data m_data;
void f() override { f_action<type, Data>{}( m_data ); }
}
}
And for each specialization, you do:
namespace A {
template <>
struct f_action<SomeType, B::SomeTypeData>
{
void operator()( B::SomeTypeData /* & or && or neither */)
{ /*Whatever*/ }
}
}
Hopefully, the definition of Impl::f won't need f_action to be
complete at that point.
Daryle W.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]