QObjectを継承するテンプレートクラスを持つことは可能ですか(その宣言にQ_OBJECTマクロがあります)?
スロット用のアダプターのようなものを作成したいのですが、スロットは任意の数の引数を取ることができます(引数の数はテンプレート引数に依存します)。
試してみたところ、リンカエラーが発生しました。このテンプレートクラスでgmakeまたはmocが呼び出されていないようです。これを行う方法はありますか?多分明示的にテンプレートをインスタンス化することによって?
テンプレートとQ_OBJECTを混在させることはできませんが、タイプのサブセットがある場合は、次のようにスロットと信号をリストできます。
class SignalsSlots : public QObject
{
Q_OBJECT
public:
explicit SignalsSlots(QObject *parent = 0) :
QObject(parent) {}
public slots:
virtual void writeAsync(int value) {}
virtual void writeAsync(float value) {}
virtual void writeAsync(double value) {}
virtual void writeAsync(bool state) {}
virtual void writeAsync(svga::SSlideSwitch::SwitchState state) {}
signals:
void readAsynkPolledChanged(int value);
void readAsynkPolledChanged(float value);
void readAsynkPolledChanged(double value);
void readAsynkPolledChanged(bool state);
void readAsynkPolledChanged(svga::SSlideSwitch::SwitchState state);
};
...
template <class T>
class Abstraction : public SignalsSlots
{...
いくつかの制限を考慮に入れます:できます。最初に慣れてください(まだ慣れていない場合) https://doc.qt.io/archives/qq/qq16-dynamicqobject.html 。 -それはそれを実装するのに役立ちます。制限について:テンプレートQObjectクラス、つまりQObjectから派生したテンプレートクラスを持つことができますが、
これがお役に立てば幸いです。
テンプレートとQ_OBJECTを混在させることはまだ不可能ですが、ユースケースによっては、新しい「接続」構文を使用できます。これにより、少なくともテンプレートスロットを使用できます。
古典的な非機能的なアプローチ:
class MySignalClass : public QObject {
Q_OBJECT
public:
signals:
void signal_valueChanged(int newValue);
};
template<class T>
class MySlotClass : public QObject {
Q_OBJECT
public slots:
void slot_setValue(const T& newValue){ /* Do sth. */}
};
望ましい使用法ですがコンパイルできません:
MySignalClass a;
MySlotClass<int> b;
QObject::connect(&a, SIGNAL(signal_valueChanged(int)),
&b, SLOT(slot_setValue(int)));
エラー:テンプレートクラスはQ_OBJECT(MySlotClassの場合)でサポートされていません。
新しい 'connect'-syntaxを使用するソリューション:
// Nothing changed here
class MySignalClass : public QObject {
Q_OBJECT
public:
signals:
void signal_valueChanged(int newValue);
};
// Removed Q_OBJECT and slots-keyword
template<class T>
class MySlotClass : public QObject { // Inheritance is still required
public:
void slot_setValue(const T& newValue){ /* Do sth. */}
};
これで、目的の「MySlotClass」オブジェクトをインスタンス化して、適切なシグナルエミッターに接続できます。
MySignalClass a;
MySlotClass<int> b;
connect(&a, &MySignalClass::signal_valueChanged,
&b, &MySlotClass<int>::slot_setValue);
結論:テンプレートスロットを使用することは可能です。 Q_OBJECTがないためにコンパイラエラーが発生するため、テンプレート信号の送信は機能しません。
テンプレートを明示的にインスタンス化してみたところ、次のようになりました。
core_qta_qt_publisheradapter.hpp:96:エラー:Q_OBJECTでサポートされていないテンプレートクラス
それが私の質問の答えだと思います。
[〜#〜]編集[〜#〜]
実際、テンプレートクラス定義全体をヘッダーに配置すると、qtプリプロセッサで処理されず、リンカーエラーが発生します。したがって、足りないメソッドを追加した場合、それが可能になるはずです。
EDIT#2
このライブラリ は、まさに私が望んでいたことを実行しました-スロットに署名が定義されていないカスタム信号/スロットメカニズムを使用するため。