Вы можете использовать CRTP для внедрения производного класса в базу. Затем вы можете определить помощника по характеристикам, чтобы определить, например, какие настройки должны использоваться для некоторого производного класса. По общему признанию, немного многословен, но теперь ваш код безопасен для типов.
Если вам нужно, чтобы базовый класс не был шаблоном, вы можете вытащить все, кроме open
, в верхний базовый класс, не являющийся шаблоном .
class AudioStreamA;
struct settingsA;
template<class T>
struct AudioStreamTraits;
template<>
struct AudioStreamTraits<AudioStreamA> {
using Settings = settingsA;
};
template<class Derived>
class AudioStreamBase
{
protected:
using StreamTraits = AudioStreamTraits<Derived>;
using Settings = typename StreamTraits::Settings;
public:
virtual
~AudioStreamBase() = default;
virtual void
open(const Settings& settings) = 0;
//...
};
struct settingsA
{
int param1;
int param2;
};
class AudioStreamA : public AudioStreamBase<AudioStreamA>
{
using Base = AudioStreamBase<AudioStreamA>;
using Base::Settings;
public:
void open(const Settings& settings) override { };
};
int main() {
AudioStreamA s;
settingsA settings;
s.open(settings);
return 0;
}
См. Пример кода здесь
Однако, если вам нужны только настройки в производном классе, вы можете просто заменить open
конструктором в производном классе:
class AudioStreamBase
{
public:
virtual
~AudioStreamBase() = default;
// ....
};
struct settingsA
{
int param1;
int param2;
};
class AudioStreamA : public AudioStreamBase
{
public:
AudioStreamA(const settingsA& settings) { } ;
};