[解決済み] operator&がオーバーロードされたときに、オブジェクトのアドレスを確実に取得するにはどうしたらよいですか?
質問
次のようなプログラムを考えてみましょう。
struct ghost
{
// ghosts like to pretend that they don't exist
ghost* operator&() const volatile { return 0; }
};
int main()
{
ghost clyde;
ghost* clydes_address = &clyde; // darn; that's not clyde's address :'(
}
どうすれば
clyde
のアドレスは?
あらゆる種類のオブジェクトに対して等しく機能するソリューションを探しています。 C++03のソリューションがあればいいのですが、C++11のソリューションにも興味があります。 可能であれば、実装に依存した動作は避けましょう。
私が認識しているのは、C++11の
std::addressof
関数テンプレートですが、ここで使用することには興味がありません。 標準ライブラリの実装者がこの関数テンプレートをどのように実装するかを理解したいのです。
どのように解決するのですか?
更新してください。
C++11では
std::addressof
の代わりに
boost::addressof
.
まず、Boostからコンパイラの回避ビットを除いたコードをコピーしてみましょう。
template<class T>
struct addr_impl_ref
{
T & v_;
inline addr_impl_ref( T & v ): v_( v ) {}
inline operator T& () const { return v_; }
private:
addr_impl_ref & operator=(const addr_impl_ref &);
};
template<class T>
struct addressof_impl
{
static inline T * f( T & v, long ) {
return reinterpret_cast<T*>(
&const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
}
static inline T * f( T * v, int ) { return v; }
};
template<class T>
T * addressof( T & v ) {
return addressof_impl<T>::f( addr_impl_ref<T>( v ), 0 );
}
を渡すとどうなるのでしょうか? への参照は、関数 ?
注
addressof
へのポインタと一緒に使用することはできません。
C++では、もし
void func();
が宣言されている場合
func
は引数を取らず、結果を返さない関数への参照です。この関数への参照は,関数へのポインタに些細な変換が可能である -- からである.
@Konstantin
: 13.3.3.2では
T &
と
T *
は関数の区別がつかない。1つ目はID変換、2つ目は関数からポインタへの変換で、どちらも"完全一致のランクを持っています(13.3.3.1.1 table 9)。
その
関数への参照
を経由して
addr_impl_ref
を選択した場合、オーバーロードの解決に曖昧さがあります。
f
というダミー引数によって解決されます。
0
であり、これは
int
に昇格する可能性があります。
long
(インテグラルコンバージョン)。
このように、単純にポインタを返すだけです。
変換演算子で型を渡すとどうなるのでしょうか?
変換演算子が
T*
の場合、曖昧さが生じます。
f(T&,long)
の場合、第2引数にIntegral Promotionが必要であるのに対し
f(T*,int)
の場合、変換演算子は最初の
(@litb に感謝)
その時
addr_impl_ref
が効いてきます。C++規格では、変換列は最大で1つのユーザ定義変換を含むことができることを義務付けています。で型を包むことで
addr_impl_ref
で、すでに変換列を強制的に使用することで、その型に付属する変換演算子を無効にしています"quot;。
したがって
f(T&,long)
が選択されます(積分処理も行われます)。
その他の型ではどうなるのでしょうか?
このように
f(T&,long)
のオーバーロードが選択されますが、これはその型が
T*
パラメータを使用します。
注:Borland互換性に関するファイルの備考から、配列はポインタに減衰せず、参照渡しされる。
このオーバーロードではどうなるのでしょうか?
を適用しないようにしたい。
operator&
がオーバーロードされた可能性があるため、この型に変換します。
規格では、以下のことが保証されています。
reinterpret_cast
は、この作業に使用することができます(@Matteo Italiaの回答:5.2.10/10を参照してください)。
Boost は
const
と
volatile
修飾子を使うことで、コンパイラの警告を回避することができます(そして、適切に
const_cast
を削除してください)。
-
キャスト
T&
からchar const volatile&
-
を剥がす。
const
とvolatile
-
を適用します。
&
演算子を使って、アドレス -
にキャストバックする。
T*
は
const
/
volatile
ジャグリングはちょっとした黒魔術ですが、(4つのオーバーロードを提供するのではなく)作業を簡略化することができます。なお
T
は非限定であるため、もし
ghost const&
であれば
T*
は
ghost const*
従って、修飾語は実際には失われていない。
EDITです。 ポインタのオーバーロードは、関数へのポインタに使用されます。私はまだ、なぜそれが 必要 とはいえ
以下は アイディーン出力 は、これを多少なりとも要約している。
関連
-
[解決済み】getline()が何らかの入力の後に使用されると動作しない 【重複あり
-
[解決済み】クラステンプレートの引数リストがない
-
[解決済み】C-stringを使用すると警告が表示される。"ローカル変数に関連するスタックメモリのアドレスが返される"
-
[解決済み】'cout'は型名ではない
-
[解決済み】リンカーエラーです。"リンカ入力ファイルはリンクが行われていないため未使用"、そのファイル内の関数への未定義参照
-
[解決済み】クラステンプレートの使用にはテンプレート引数リストが必要です
-
[解決済み】C++ - 適切なデフォルトコンストラクタがない [重複]。
-
[解決済み】デバッグアサーションに失敗しました
-
[解決済み] Linux上で動作するC++コードのプロファイリングを行うにはどうすればよいですか?
-
[解決済み] C++ ダブルアドレス演算子?(&&)
最新
-
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-stringを使用すると警告が表示される。"ローカル変数に関連するスタックメモリのアドレスが返される"
-
[解決済み】C++コンパイルタイムエラー:数値定数の前に期待される識別子
-
[解決済み】Cygwin Make bash コマンドが見つかりません。
-
[解決済み] クラスにデフォルトコンストラクタが存在しない。
-
[解決済み】'cout'は型名ではない
-
[解決済み】fpermissiveフラグは何をするのですか?
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み】浮動小数点数の乱数生成
-
[解決済み】C++ - ステートメントがオーバーロードされた関数のアドレスを解決できない。
-
[解決済み】std::cin.getline( ) vs. std::cin