2013-05-08 7 views
19

<type_traits>の一部の型変換は、コア言語の構文を使用して表すこともできます(例:std::add_const<T>::typeconst Tと同じです)。 Dttoのstd::add_lvalue_reference、およびおそらく他のもの。これらの型形質の用途は何ですか?std :: add_constなどの使用例

私は完全に標準はそれらなしで「不完全なツールボックス」を提供されるだろう理解し、そして私は、メタな方法でこのようなものの使用を想像することができます

template<typename In, template <typename> class Modifier> 
struct Apply { 
    typedef typename Modifier<T>::type Out; 
}; 

Apply<int, std::add_const> 

は、これらの特性のために、他のユースケースがありますそれは構文的に表現することができますか、あるいは単に「完全性の意味から」と、時折のメタ・ユースのために含まれていますか?

+1

'T'が既に' const'の場合はどうなりますか? –

+1

@PeterWood [Works fine](http://ideone.com/mhY62n)、少なくともgcc 4.7.2 – Angew

+2

@PeterWoodすでに修飾されていれば、標準で要求されているのと同じ型を返します。 – jrok

答えて

19

これらの形質がブーストおよび標準、N1345にそれらを追加する提案から来る、アンドレイアレキが言うように引用:

「私はadd_constadd_volatileadd_cv、およびadd_pointerを追加するための対称引数を理解し、しかし、私はそれらを排除することに賛成論争するだろう。言語提供の等価物は単により簡単でより良いです。 、例えば、add_const ::タイプがT constのと同じであるので、表面的にadd_const、add_volatileとadd_cvクラスは、無関係です:

著者注:

は同じ提案はまた、この理論的根拠を提供しますすべてのTに対して(現在のところ、これは関数型には適用されませんが、issue 295がこれを扱います)。ブーストからの経験は、これらのテンプレートは、以下の理由により、ライブラリー中に存在するため、複数のユーザーが求めているということですが:(a)は一部のユーザーは、これらのより明示的な見つける - に建てられた」のようなもののような変態特にテンプレート、ユーザーを組み合わせる場合これらのテンプレートが提供する「ドキュメンテーション」です。 (b)は、すべてのユーザーがCV-予選参照が許可され、効果はありません、またはそのCV-予選すでにCV-資格のあるタイプが許可されていると効果はありませんされていることを認識しているわけではありません。 (c)コンパイラは、参照であるか、すでにcv修飾子を持っている型をcv修飾するときに、これらのメッセージが抑止されるようにこれらのテンプレートを実装することができます。 add_reference用も

、(標準でadd_lvalue_referenceに改名):

著者注:add_referenceテンプレートは、ブーストタイプの特性ライブラリの背後にあるオリジナルの動機の一つでした。しかし、issue 106への解決は、テンプレートをほとんど冗長に見えるようにします。それにもかかわらず、add_referenceは、誤ってテンプレートコード内の参照への参照を作成するときに、コンパイラの警告を抑制するのに役立ちます。

+4

' add_ {l、r} value_reference'も 'void'でうまくいきます。 – Xeo

5

これらの形質は時折メタ使用するために提供されています。これは、メタプログラミングの中で、必要なcv修飾子を転送することを可能にします。この場合

template<class T,template<class> class Trait> 
struct transform 
{ 
    /* working with T creating newT*/ 

    typedef Trait<newT>::type type; 
}; 

template<class T> 
struct special_transform 
    : transfrom<T, std::add_const> 
{}; 

あなたはconststd::add_constを置き換えることができませんでした。私が知っている

1

のみ使用事例を以下に示す:

struct F 
{ 
    bool f() const { return true; } 
    bool f() { return false; } 
}; 
assert(!F{}.f()) 
assert(std::add_const_t<F>{}.f()); 

またCV-REF修飾メンバ関数機能の試験のために必要な、異なるオーバーロードのために異なるかもしれない(のみlref-ため資格の近代的なC++)は便利なstd::as_const機能を持っています

struct F 
{ 
    int g() & { return 1; } 
    int g() const & { return 2; } 
    int g() && { return 3; } 
    int g() const && { return 4; } 
}; 
F f; 
assert(f.g() == 1); 
assert(std::as_const(f).g() == 2); 
assert(F{}.g() == 3); 
assert(std::add_const_t<F>{}.g() == 4); // rarely needed, but if needed, then it helps 
1

add_constは、型推論の競合を解決するために使用することができます。我々はwrapper<T const>を使用する場合

template <typename T> 
class wrapper; 

template <typename T> 
bool operator==(wrapper<T> const& w, T const& t); 

、問題が発生する:

wrapper<int const> w = { 42 }; 
assert(w == 42); // Error: conflicting deduced types 

T

は、同時に両方 int int constなると推定されます。これは、 add_constを使用して解決できます。

template <typename T> 
bool operator==(wrapper<T> const& w, add_const_t<T>& t); 
+0

興味深いユースケースです。 2番目の関数パラメータを推論されていないコンテキストにするその他のものも動作しますが、これは非常に簡潔です。 – Angew

関連する問題