C
Christoph Mathys
Hello!
Well, nothing too spectacular, but I'd still be interested in how one
solves this problem in a clean way: I need to a implement a class
which uses different APIs and provides a uniform interface (APIs are
fixed at compiletime). I can't use an ABC directly because the class
is only used as value type. But I'd still like to have an interface
common to all classes, defined at a single place.
I had the following ideas to this problem:
1. Implement a completely independent version of the class for every
platform. This is easy to do and to use, but you don't have any kind
of common interface between the classes except convention alone.
2. Use a template class which just declares the method (some kind of
static interface) and fully specialize the class for every platform.
However, after a bit more thinking this solution does not seem to have
much advantages as the compiler will only give an error if you
actually try to invoke a missing function (e.g. not specialized, only
declared). You have however a common place were methods are declared
which *should* be there.
3. Define an ABC and pimpl it inside an implementation providing the
needed NVI. I don't need to squeeze cycles, but seems a bit overkill
for something that is known at compiletime.
Some toy code for variant 2 is below.
Thanks for ideas!
Christoph
#include <string>
template<typename T>
struct MyInterface {
std::string get() const;
void blup();
T node_;
};
struct AsdfApi {
std::string get_name() const
{ return name_; }
std::string name_;
};
struct XyzApi {
std::string GetName() const
{ return name_; }
std::string name_;
};
#ifdef USE_ASDF
template<> std::string MyInterface<AsdfApi>::get() const
{ return node_.get_name(); }
typedef MyInterface<AsdfApi> IfToUse;
#else
template<> std::string MyInterface<XyzApi>::get() const
{ return node_.GetName(); }
typedef MyInterface<XyzApi> IfToUse;
#endif
int main()
{
IfToUse use;
use.get();
// use.blup(); // compile error if uncommented
return 0;
}
Well, nothing too spectacular, but I'd still be interested in how one
solves this problem in a clean way: I need to a implement a class
which uses different APIs and provides a uniform interface (APIs are
fixed at compiletime). I can't use an ABC directly because the class
is only used as value type. But I'd still like to have an interface
common to all classes, defined at a single place.
I had the following ideas to this problem:
1. Implement a completely independent version of the class for every
platform. This is easy to do and to use, but you don't have any kind
of common interface between the classes except convention alone.
2. Use a template class which just declares the method (some kind of
static interface) and fully specialize the class for every platform.
However, after a bit more thinking this solution does not seem to have
much advantages as the compiler will only give an error if you
actually try to invoke a missing function (e.g. not specialized, only
declared). You have however a common place were methods are declared
which *should* be there.
3. Define an ABC and pimpl it inside an implementation providing the
needed NVI. I don't need to squeeze cycles, but seems a bit overkill
for something that is known at compiletime.
Some toy code for variant 2 is below.
Thanks for ideas!
Christoph
#include <string>
template<typename T>
struct MyInterface {
std::string get() const;
void blup();
T node_;
};
struct AsdfApi {
std::string get_name() const
{ return name_; }
std::string name_;
};
struct XyzApi {
std::string GetName() const
{ return name_; }
std::string name_;
};
#ifdef USE_ASDF
template<> std::string MyInterface<AsdfApi>::get() const
{ return node_.get_name(); }
typedef MyInterface<AsdfApi> IfToUse;
#else
template<> std::string MyInterface<XyzApi>::get() const
{ return node_.GetName(); }
typedef MyInterface<XyzApi> IfToUse;
#endif
int main()
{
IfToUse use;
use.get();
// use.blup(); // compile error if uncommented
return 0;
}