2016-06-30 14 views
10

ちょうどこれに似た質問があります。なぜconstオブジェクトのメンバ変数がconstでないのです

#include <iostream> 
using namespace std; 

struct A { 
    A() : a{1} {}; 
    int a; 
}; 

template <typename Which> 
struct WhichType; 

int main() { 
    const A a; 
    const A& a_ref = a; 
    const A* a_ptr = &a; 
    WhichType<decltype(a.a)> which_obj; // template evaluates to int 
    WhichType<decltype(a_ref.a)> which_ref; // template evaluates to int 
    WhichType<decltype(a_ptr->a)> which_ptr; // template evaluates to int 

    return 0; 
} 

なぜテンプレートはconst intの代わりintにはならないのですか?

答えて

9

decltypeは、余分な括弧で囲まれていないオペランドの「宣言型」を提供します。

式の実際のタイプ、つまりconst intを取得するには、decltype((a.a))などと書く必要があります。

decltypeは、名前以外の左辺値式の参照型を常に返します。

+0

したがって、 'decltype' ** always **は、コードで定義されている名前の宣言の型だけを返しますか?そこに行くために取られたすべてのオブジェクトの 'const'ness、' ref'nessまたは 'volatile'nessを無視しますか?例えば ​​'const'オブジェクト内の変数? – Curious

+2

@Curiousオペランドが変数またはメンバーアクセス式の名前だけである特定の場合、yesは宣言の型を示します。囲みオブジェクトのcv修飾により、式の型が変更されますが、余分なカッコを使用すると、式の型だけが取得されます。同様のことがバリューカテゴリに適用されます。 – Brian

2

識別子(またはメンバ)の名前が渡されると、宣言の型が返されます。

異なる式が渡された場合、それはあなたが望むものに近いものを返しますが、参照修飾されたものです。

WhichType<std::remove_reference_t<decltype((a_ptr->a))>> which_ptr; // template evaluates to const int! 

live example か、L/Rのvaluenessたい場合:

WhichType<decltype((a_ptr->a))> which_ptr2; // template evaluates to const int& 
WhichType<decltype(((const A){}.a))> which_ptr3; // template evaluates to const int 

をあなたはそれここに "本物の" 右辺値参照にする&&を追加することができます。

WhichType<decltype(((A){}.a))&&> which_ptr4; // template evaluates to int&&! 

live example

+0

それは素晴らしいです! Scott MeyerのC++の本でこのメソッドが使われているのを見たので、それを使うときにそれについて考えることさえできませんでした。この微妙なこと以外にも 'decltype'について知っておくべきことがありますか? – Curious

+0

'(const A){}'の代わりに 'std :: declval ()'を使うことができます。 – Jarod42

+1

@jarrodは間違いなく長いです! – Yakk

関連する問題