[解決済み] Qt 5 でオーバーロードされた信号とスロットを接続する
質問
Qt 5 の新しいシグナル/スロット構文(メンバー関数へのポインターを使用)を理解するのに苦労しています。 シグナルスロットの新しい構文 . これを変更してみた。
QObject::connect(spinBox, SIGNAL(valueChanged(int)),
slider, SLOT(setValue(int));
をこれに変更します。
QObject::connect(spinBox, &QSpinBox::valueChanged,
slider, &QSlider::setValue);
が、コンパイルしようとするとエラーになります。
error: no matching function for call to
QObject::connect(QSpinBox*&, <unresolved overloaded function type>, QSlider*&, void (QAbstractSlider::*)(int))
Linuxでclangとgccで試しましたが、どちらも
-std=c++11
.
何が間違っているのか、どうすれば直るのか?
解決方法は?
ここで問題となるのは
二
という名前のシグナルがあります。
QSpinBox::valueChanged(int)
と
QSpinBox::valueChanged(QString)
. Qt 5.7 からは、希望するオーバーロードを選択するためのヘルパー関数が提供されているので、以下のように書くことができます。
connect(spinbox, qOverload<int>(&QSpinBox::valueChanged),
slider, &QSlider::setValue);
Qt 5.6 以前のバージョンでは、正しい型にキャストすることで、どちらを選びたいかを Qt に伝える必要があります。
connect(spinbox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
slider, &QSlider::setValue);
そうなんです、それは 醜い . でも、これは仕方がないことなんです。今日のレッスンは シグナルやスロットに負荷をかけないようにしましょう
追記 : キャストで本当に困るのは
- クラス名が2回繰り返される
-
である場合でも、戻り値を指定しなければならない。
void
(シグナルの場合)。
だから、私は時々このC++11のスニペットを使っていることに気がついた。
template<typename... Args> struct SELECT {
template<typename C, typename R>
static constexpr auto OVERLOAD_OF( R (C::*pmf)(Args...) ) -> decltype(pmf) {
return pmf;
}
};
使用方法
connect(spinbox, SELECT<int>::OVERLOAD_OF(&QSpinBox::valueChanged), ...)
個人的にはあまり意味がないと思っています。Creator(またはIDE)がPMFを取得する操作をオートコンプリートする際に、自動的に正しいキャストを挿入するようになれば、この問題は自然に解消されると思います。しかし、その一方で...
注意:PMFベースの接続構文 はC++11を必要としません !
補遺2
Qt 5.7 では、この問題を解決するためのヘルパー関数が追加され、上記の私の回避策に倣っています。主なヘルパーは
qOverload
(他にも
qConstOverload
と
qNonConstOverload
).
使用例(docsより)。
struct Foo {
void overloadedFunction();
void overloadedFunction(int, QString);
};
// requires C++14
qOverload<>(&Foo:overloadedFunction)
qOverload<int, QString>(&Foo:overloadedFunction)
// same, with C++11
QOverload<>::of(&Foo:overloadedFunction)
QOverload<int, QString>::of(&Foo:overloadedFunction)
補遺3 オーバーロードされたシグナルのドキュメントを見ると、オーバーロードの問題の解決策がドキュメントに明記されています。例えば https://doc.qt.io/qt-5/qspinbox.html#valueChanged-1 にはこう書かれています。
注:シグナルvalueChangedはこのクラスでオーバーロードされています。関数ポインタの構文を使ってこのシグナルに接続するために、Qtはこの例に示すように関数ポインタを取得する便利なヘルパーを提供しています。
connect(spinBox, QOverload<const QString &>::of(&QSpinBox::valueChanged), [=](const QString &text){ /* ... */ });
関連
-
[解決済み] エラーが発生する。ISO C++は型を持たない宣言を禁じています。
-
[解決済み】 != と =! の違いと例(C++の場合)
-
[解決済み】テンプレートの引数1が無効です(Code::Blocks Win Vista) - テンプレートは使いません。
-
[解決済み】fpermissiveフラグは何をするのですか?
-
[解決済み】#include<iostream>は存在するのですが、「識別子 "cout "は未定義です」というエラーが出ます。なぜですか?
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み】C++ - 適切なデフォルトコンストラクタがない [重複]。
-
[解決済み】デバッグアサーションに失敗しました
-
[解決済み] 1ビットのセット、クリア、トグルはどのように行うのですか?
-
[解決済み] static_cast, dynamic_cast, const_cast, reinterpret_cast はいつ使うべきですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C++ クラスヘッダが含まれているときに「不明な型」があるのはなぜですか?重複
-
[解決済み】C++ - 解放されるポインタが割り当てられていないエラー
-
[解決済み】抽象クラス型の無効なnew-expression
-
[解決済み】Cygwin Make bash コマンドが見つかりません。
-
[解決済み】C++の変数はイニシャライザーを持っているが、不完全な型?
-
[解決済み】#include<iostream>は存在するのですが、「識別子 "cout "は未定義です」というエラーが出ます。なぜですか?
-
[解決済み】クラステンプレートの使用にはテンプレート引数リストが必要です
-
[解決済み】1つ以上の多重定義されたシンボルが見つかる
-
[解決済み】浮動小数点数の乱数生成
-
[解決済み】Visual Studioのデバッガーエラー。プログラムを開始できません 指定されたファイルが見つかりません