[解決済み] is_base_of`はどのように機能するのですか?
質問
次のコードはどのように動作するのでしょうか?
typedef char (&yes)[1];
typedef char (&no)[2];
template <typename B, typename D>
struct Host
{
operator B*() const;
operator D*();
};
template <typename B, typename D>
struct is_base_of
{
template <typename T>
static yes check(D*, T);
static no check(B*, int);
static const bool value = sizeof(check(Host<B,D>(), int())) == sizeof(yes);
};
//Test sample
class Base {};
class Derived : private Base {};
//Expression is true.
int test[is_base_of<Base,Derived>::value && !is_base_of<Derived,Base>::value];
-
注意点として
B
はプライベートベースであることに注意してください。これはどのように機能するのでしょうか? -
以下のことに注意してください。
operator B*()
は const です。なぜそれが重要なのでしょうか? -
なぜ
template<typename T> static yes check(D*, T);
よりもstatic yes check(B*, int);
?
ノート
: の縮小版(マクロが削除されている)です。
boost::is_base_of
. そして、これは様々なコンパイラで動作します。
どのように解決するのですか?
それらが関連している場合
ちょっと仮定してみましょう。
B
が実際に
D
. そして
check
を呼び出す場合、どちらのバージョンも実行可能です。
Host
に変換することができます。
D*
と
B*
. で記述されているように、ユーザーが定義した変換シーケンスです。
13.3.3.1.2
から
Host<B, D>
から
D*
であり
B*
をそれぞれ作成する。クラスを変換できる変換関数を見つけるために,以下の候補関数を合成し,最初の
check
関数に従って
13.3.1.5/1
D* (Host<B, D>&)
最初の変換関数は候補ではありません。
B*
には変換できないからです。
D*
.
2番目の関数については、以下の候補が存在します。
B* (Host<B, D> const&)
D* (Host<B, D>&)
これらはホストオブジェクトを受け取る2つの変換関数候補です。最初のものはconst参照でそれを取り,2番目はそうではありません。したがって、2番目のものはconstでない
*this
オブジェクト(
オブジェクトの暗黙の引数
)による
13.3.3.2/3b1sb4
への変換に使用されます。
B*
に変換し、2つ目の
check
という関数があります。
もし、あなたが を削除する を削除すると、次のような候補になります。
B* (Host<B, D>&)
D* (Host<B, D>&)
これは、もう constness で選択できないことを意味します。通常のオーバーロード解決シナリオでは、通常、戻り値の型はオーバーロード解決に参加しないので、呼び出しは曖昧になります。しかし、変換関数の場合は、裏口がある。もし2つの変換関数が同じように良いなら、それらの戻り値の型は、次のように誰が最も良いか決定する。
13.3.3/1
. したがって,もしconstを削除するならば,1番が取られることになる,なぜなら
B*
への変換がうまくいくからです。
B*
よりも
D*
に
B*
.
さて、どのユーザ定義変換シーケンスが良いでしょうか?番目のチェック関数のもの、それとも1番目のチェック関数のものでしょうか?ルールは、ユーザー定義の変換シーケンスは、同じ変換関数またはコンストラクタを使用する場合にのみ比較することができるということです。
13.3.3.2/3b2
. これはまさにこの場合です。両方とも2番目の変換関数を使用します。このように
const
が重要なのは、コンパイラに2番目の変換関数を取らせるからです。
比較することができるので - どちらが良いのでしょうか?ルールは、変換関数の戻り型から変換先の型へのより良い変換が勝つということです(これもまた
13.3.3.2/3b2
). この場合
D*
に変換されます。
D*
よりも
B*
. このように、最初の関数が選択され、私たちは継承を認識します
を必要としなかったことに注意してください。
実際に
をベースクラスに変換する必要がないので、それによって
私的継承
からの変換が可能だからです。
D*
から
B*
による継承の形態には依存しません。
4.10/3
関連性がない場合
ここで、それらが継承によって関連していないと仮定してみましょう。したがって、最初の関数については、次のような候補があります。
D* (Host<B, D>&)
そして、2つ目は、別のセットです。
B* (Host<B, D> const&)
を変換することはできないので
D*
を
B*
もし継承関係がなければ,2つのユーザー定義変換シーケンスの間に共通の変換関数がないことになります! したがって、次のようになります。
あいまい
もし最初の関数がテンプレートでなければ。によれば、テンプレートでない関数が同じように優れている場合、テンプレートは第二の選択肢になります。
13.3.3/1
. このように、テンプレートではない関数(2つ目)を選択すると
B
と
D
!
関連
-
[解決済み】変数 '' を抽象型 '' と宣言できない。
-
[解決済み] error: 'if' の前に unqualified-id を期待した。
-
[解決済み】c++で.txtファイルから2次元の配列に読み込む
-
[解決済み] explicit キーワードの意味は?
-
[解決済み] 文字列の単語を反復処理するにはどうすればよいですか?
-
[解決済み] 1ビットのセット、クリア、トグルはどのように行うのですか?
-
[解決済み] C++11では、標準化されたメモリモデルが導入されました。その意味するところは?そして、C++プログラミングにどのような影響を与えるのでしょうか?
-
[解決済み] Linux上で動作するC++コードのプロファイリングを行うにはどうすればよいですか?
-
[解決済み] Javaはパラメータのデフォルト値をサポートしていますか?
-
[解決済み] 0.1fを0にすると、なぜ10倍もパフォーマンスが落ちるのですか?
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】致命的なエラー LNK1169: ゲームプログラミングで1つ以上の多重定義されたシンボルが発見された
-
[解決済み】cc1plus:エラー:g++で認識されないコマンドラインオプション"-std=c++11"
-
[解決済み】エラー:strcpyがこのスコープで宣言されていない
-
[解決済み】Visual Studio 2013および2015でC++コンパイラーエラーC2280「削除された関数を参照しようとした」が発生する
-
[解決済み】#include<iostream>は存在するのですが、「識別子 "cout "は未定義です」というエラーが出ます。なぜですか?
-
[解決済み】クラステンプレートの使用にはテンプレート引数リストが必要です
-
[解決済み] 非静的データメンバの無効な使用
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み] 解決済み] `pthread_create' への未定義の参照 [重複] [重複
-
[解決済み] 配列のベクトルを扱う正しい方法