2013-10-04 7 views
5

と同じconst性と値を返す:は、私はこれらのオーバーロードと機能を持っているパラメータ

A& f(B& b) 
{ 
    return b.a; 
} 

const A& f(const B& b) 
{ 
    return b.a; 
} 

return文はbがconstのであればconstのあるいくつかの値を返すはるかに複雑ロジックすることができます。たとえば、Bはコンテナのコンテナであり(おそらくより深いネスティングを持つ可能性があります)、1つの要素を検索しています。この場合、関数をコピーするのは良い考えではありません。同じ結果を達成するための選択肢はありますか?

私はいくつかの解決策について考えることができますが、私はそれらを本当に好きではありません。

template <typename T> 
auto f(T& b) -> decltype(b.a) 
{ 
    return b.a; 
} 

それは動作しますが、そのb.aはそう簡単ではありません場合(コンテナ内でのように)複雑になります。

A& f(B& b) 
{ 
    return b.a; 
} 

const A& f(const B& b) 
{ 
    return f(const_cast<B&>(b)); 
} 

これは動作しますが、ハックのような感じです。シンプルでクリーンなソリューションはありますか?

+1

'A&f(B&b){return f(const_cast (n));}'はどうですか?'const'を追加することはハックではなく、あなたはまだすべての保証を得ることができます。私は関数がconst入力に常に働くことができると仮定しています。 – Jon

+0

次に、出力をconst_castしなければならないので、基本的に同じです。しかし、はい、それはもっと安全です。 – petersohn

答えて

3

私はconstバージョンの観点から非constバージョンを実装しますが、これとは逆の方法で実装します。

A& f(B& b) 
{ 
    return const_cast<A&>(f(static_cast<B const&>(b))); 
} 

これは、ビューの可変性の観点からビットより安全になります。

template <typename T> 
auto f(T& b) -> std::conditional_t<std::is_const<T>{}, A const&, A&> 
{ 
    return b.a; 
} 

std::conditional_t(C++ 14)がstd::conditionalを使用し、その後、サポートされていない場合:このことについてどのようにテンプレートのバージョンについては

typename std::conditional<std::is_const<T>{}, A const&, A&>::type 

お役に立てば幸いです。

+1

ええ、私はあなたが正しいと思う、非constバージョンはconst oneの面で実装する必要があります...私はいつもどちらの方法が正しいか混乱します。 –

+0

'std :: conditional'に対して' is_const {} 'を' std :: is_const :: value'にするべきではありませんか? – 0x499602D2

+0

@ 0x499602D2:暗黙の変換関数 'constexpr operator bool()const'があります。これは暗黙的に呼び出され、 'value'を自動的に取得します。 – Nawaz

2

fがデータを変更しないことがわかっている場合、const_castはハックではなく、完全に正当な解決策です。

この典型的な例は、strchrです。これは、文字列内の文字を検出します。我々はを知っていますが、これは突然変異しませんが、非const過負荷を提供することによって突然変異可能な文字列を突然変異させることは可能です。しかし、非constバージョンはconstのオーバーロードの観点からうまく実装できます。

const_castを使用することは違反ではありません。定数オブジェクトを変更するのは唯一の違反です。

2

可能な解決策:

template<typename B> 
struct Return_type { typedef A &Type; }; 

template<typename B> 
struct Return_type<B const &> { typedef A const &Type; }; 

template<typename B> 
typename Return_type<B>::Type f(B &&b) 
{ 
    return b.a; 
} 

EDIT:

C++ 14は、関数の戻り値の型推論を持つことになりますので、これは動作するはずです:

template<typename T> 
auto &f(T &&b) 
{ 
    return b.a; 
} 

GCC 4.8.1は、すでにコンパイルそれ。

+0

新しいスタイルのtypedefは 'Type = A const&;'を使っています。 – Nawaz

+0

'auto'はconstを捨てませんか? – Hulk

+0

+1はC++ 14ソリューションです。私もそれについて考えましたが、私はC++ 11で有効な解決策しか考えていませんでした。 – petersohn

関連する問題