2010-12-08 5 views
3

標準(§5.2.11)によれば、const_castはcv修飾子(constまたはvolatile)をキャストします。なぜconst_castはあなたがキャストするものを述べる必要がありますか?

ここに簡単な例があります。その後、あなたは参照ツーconstの作成

class Bar { ... }; 
void foo_ptr(Bar*); 
void foo_ref(Bar&); 

Bar b; 
const Bar& cb = b; 

をして、あなたは適切なはconst_castを使用することにより、いずれかの関数を呼び出すことができます。

まず、ポインタと参照を取る二つの関数を宣言します
foo_ptr(const_cast<Bar*>(&cb)); 
foo_ref(const_cast<Bar&>(cb)); 

ここに私の質問があります:const_castは他のキャストのために設計されたものではありませんので、あなたがキャストするものは明白ではありませんか?私が何かをしようとすると、a)は、コンパイラは私を停止する必要があり

foo_ptr(const_cast<>(&cb)); 
foo_ref(const_cast<>(cb)); 

私は次の2つの理由を考えることができます。つまり、なぜ言語は、私は単純に言うことはできません。

foo_ptr(const_cast<int*>(&cb)); 
foo_ref(const_cast<int&>(cb)); 

と明示的に私は、不正な動作から私を保つことができ、それにキャストてるタイプを述べるために私を強制することによって:のような、狂いました。私は、コンパイラに私を修正させるだけの何かを間違って書いてもらうことを好む言語が好きならば、奇妙なので、この(仮説的な)説明は弱いと思う。

b)変数がconstおよびvolatileの両方である場合は、あいまいさが考えられます。その場合、コンパイラは、どちらか一方または両方をキャストしようとしているかどうかを知る方法がありません。

それはなぜですか、または別の理由がありますか?

答えて

5

const_castを追加したり、constvolatile修飾子を削除するために使用することができます。このような構文が許されたのであれば、次のすべてがconst_cast<>(&cb)の合法的な目的のタイプのようになります。

Bar*     (1) 
const Bar*   (2) 
volatile Bar*  (3) 
const volatile Bar* (4) 

あなたは(1)を意図しています。 (2)は通常は愚かですが、恐らくどこかで、おそらくいくつかのテンプレートコードで発生する可能性が考えられます。 (3)(4)が実際問題です。const資格を削除し、volatile資格をすべて1つのキャストで追加できます。

あなたは、キャストのペアでconst_castvolatile_castを既存のconst_castを交換し、ケース(2)を禁止することができ、ターゲットタイプなしでどちらかを使用することができます。しかし、キャスト式の型を知ることはより困難です。キャスト式が資格を追加するか削除するかを知るには、ソース式のタイプが何であるかを知る必要があります。

template <typename T> 
T* remove_const(const T* p) { 
    return const_cast<T*>(p); 
} 

あなたは簡単に両方の暗黙的remove_volatileためとadd_constadd_volatileのための同様の機能を、書くことができます:

あなたが望む結果を得るために、関数テンプレートを使用することができなかった理由はありません。

+0

もちろん、演算子は 'const_cast <>(&b)'(bは 'const'ではありません)と結果セットの同じセットを許可します。したがって、ボラティリティを扱っていなくても、Alexandros const_cast <>はconstをトグルするか、デフォルトを追加または削除するかを指定します(後者の場合、それは誤った名前になります)。あなたが言うように、テンプレートでは、あなたが始めたことを知らずにconst型または非const型を得ることが望ましいことがよくあります。 –

+0

@トニー:bについての良い点は、constである必要はありません。より一般的には、const_castもconstを追加できることは分かっていましたが、私の暗黙の前提は誰もそれをしないということです(他の方法もあるので)。 –

+2

そして、私たちはマルチレベルのポインタについても話していません:) –

1

私はJames McNellisが既に重要な理由で触れたと思います。 const_castは、を加えてを加え、恒常性/揮発性を除去することができる。あなたが望むものが必ずしも明確ではない。

私はタイプconst fooの引数にconst_castを呼び出すと、それは私がそれがconstを非作る、またはそれにvolatileを追加したい意味ですか?または、ちょうどconst修飾子を保持する必要がありますか?私がタイプ(非const)fooのオブジェクトでそれを呼び出すと、それはconstを追加すべきですか?それとも、const-nessを取り除き、型のオブジェクト(非const)fooを返すことを前提としていますか?

もう一つの理由は単に一貫性があるかもしれません。

static_cast<T>(x)dynamic_cast<T>(x)reinterpret_cast<T>(x)テンプレートのような構文なしでconst_cast(x)になるのは奇妙に見えます。

+0

* add * constについて:これは単にconstを追加することができるので他の方法でconstを追加することができます)、なぜconst_castにconstを追加する必要があるのですか? –

+0

一貫性について:はい、確かに、それは正当なポイントです。 –

0

主な理由は、const_cast使用して、あなたが

Foo * * * volatile * const 

Foo * const * volatile * * 

からキャストできるということです、先の型が何であるか本当に明白ですか?

関連する問題