C++11戻り型後置構文の使用

3825 ワード

C++11の新しい標準が追加されたautoは、変数タイプを自動的に推定するだけでなく、decltypeと組み合わせて関数の戻り値を表すこともできます.これらの新しい特性は、より簡潔で現代的なコードを書くことができます.
汎用プログラミングでは、パラメータの演算により戻り値のタイプを得る必要がある場合があります.
次の例を見てみましょう.
#include
using namespace std;


template <typename R,typename T, typename U>
R add(T t,U u)
{
    return t+u;
}

int main()
{
    int a=1;
    float b=2.0;
    auto c = add<decltype(a+b)>(a,b);
}

我々はa+bタイプが何であるかに関心を持たない.なぜならdecltype(a+b)によって直接戻り値タイプを得るだけでよいからである.しかし、上記のように使用するのは不便です.外部はパラメータ間でどのように演算すべきか分からないので、add関数だけが戻り値をどのように導くべきかを知っています.
では、関数定義でdecltypeで直接戻り値を取得できますか?たとえば、次のようになります.
template <typename T, typename U>
decltype(t+u) add(T t,U u)           //    ,t,u   
{
    return t+u;
}

実行後、コンパイラはエラーをプロンプトし、decltype(t+u)のtとuがこの役割ドメインで宣言されていないことを示します.t,uはパラメータリストにあり,C++の戻り値は前置構文であるため,戻り値定義時にパラメータ変数は存在しない.
この例では、以下のように書き表すことができます.
template <typename T, typename U>
decltype(T()+U()) add(T t,U u)       
{
    return t+u;
}

T,Uは無パラメトリック関数のクラスである可能性があることを考慮すると,正しい書き方はこうであるべきである.
template 
decltype((*(T*)0)+(*(U*)0)) add(T t,U u)       
{
    return t+u;
}

decltypeの使用に成功して戻り値の導出が完了したが、書き方が難解すぎて、戻り値タイプの導出におけるdecltypeの使用難易度が大幅に増加し、コードの可読性が低下する.したがって,C++11に戻りタイプ後置構文を追加し,decltypeとautoを組み合わせて戻り値タイプの導出を完了する.戻りタイプの後置構文はautoとdecltypeを組み合わせて使用されます.上のadd関数は、新しい構文を使用して次のように書くことができます.
template <typename T, typename U>
auto add(T t,U u) ->decltype(t+u)       
{
    return t+u;
}


この文法をさらに説明するために、もう一つの例を見てみましょう.
#include
using namespace std;


int& foo(int& i);
float foo(float& f);

template <typename T>
auto func(T& val) -> decltype(foo(val))
{
    return foo(val);
}

この例ではdecltypeを用いて戻り値の後置構文と組み合わせてfoo(val)が現れる可能性のある戻り値タイプを容易に導出しfuncに用いた.
戻り値タイプの後置構文は、関数の戻り値タイプがパラメータに依存し、戻り値タイプを特定しにくいという問題を解決するためです.この構文があれば,戻り値タイプの導出を明確に記述できる.