【Effective modern C++精製】『タイプ導出』-Item 2:『autoのタイプ導出』
7121 ワード
aotoと関数テンプレートのパラメータタイプは類似の導出規則を導く
関数テンプレートタイプ導出と比較
template<typename T>
void f(ParamType);
f(expr);
auto
によって変数が宣言されると、auto
はテンプレート内のT
と同じ役割を果たし、変数のタイプ説明子はテンプレートのParamType
の役割を果たす.auto x = 27; // auto
const auto cx = x; // const auto
const auto& rx = x; // const auto&
関数テンプレートのタイプ導出と同様にautoタイプ導出も3つのcaseに分けられる.
Case1. タイプ説明子は、汎用参照ではなくポインタ/参照です.
int x = 27;
const auto& rx = x; // const int&
Case2. タイプ説明子が共通参照の場合
int x = 27;
const int cx = 27;
auto&& uref1 = x; // x , uref1's type => int&
auto&& uref2 = cx; // cx const , uref2's type => const int&
auto&& uref3 = 27; // 27 , uref3's type => int&&
Case3. タイプ説明子はポインタでも参照でもない
auto x = 27; // x'type => int
const auto cx = x; // x'type => const int
関数と配列の場合
const char name[] = "abc";
auto arr1 = name; // arr1'type => const char*
auto& arr2 = name; // arr2'type => const char(&)[4]
-------------
void someFunc(int,double);
auto func1 = someFunc; // func1'type => void(*)(int,double)
auto& func2 = someFunc; // func2'type => void(&)(int,double)
aotoと関数テンプレートのパラメータタイプの導出の違い
C++11は、以下のように初期化の価値のある方法を追加しました.
int x1 = 27;
int x2(27);
int x3 = {27};
int x4{27};
4つの構文ですが、結果は同じです.つまり、intタイプ変数を作成します.同様に、この構文はautoに適用されます.
auto x1 = 27;
auto x2(27);
auto x3 = {27};
auto x4{27};
しかし、この2つの初期化構文の意味は異なり、
{args...}
で定義された変数を使用し、そのタイプは実際にはstd::initializer_list
であり、値27の要素を含む.関数テンプレートタイプによって導出される規則では、autoのように
{args...}
という初期化リストの形式を自動的に適合させることはサポートされていない.template<typename T>
void f(T param);
f({1,2,3}); // !!! T !!!
auto x{1,2,3}; // OK!!!
関数テンプレートタイプの導出は、次のようにのみ行います.
templateT>
void f(std::initializer_list initList);
f({1,2,3}); // !!!
したがって、autoと関数テンプレートのタイプが導いた本当の違いは、autoが天然に
std::initializer_list
をサポートする{args...}
の初期化方式であり、関数テンプレートはだめである.関数の戻りにautoが使用され、lambdaパラメータが使用される場合
C++14 autoは、関数宣言の戻りタイプに使用される場合、戻り値が導出可能であることを示す.しかし、自然導出
std::initializer_list
、すなわち{args...}
の形で戻ることはサポートされていない.ここで、autoは「autoタイプ導出ではなく、テンプレートタイプ導出をサポートする」ことを提供する.auto createInitList()
{
int a = 27;
return a; // int
}
auto createInitList()
{
return {1,2,3}; // !!!
}
autoはlambda式のパラメータにも使用できます.同様に、autoタイプの導出ではなく、パラメータが「関数テンプレートタイプ導出」をサポートすることを示します.したがって、
initializer_list
の{args...}
の自然導出もサポートされていない.std::vector v;
...
auto resetV =
[&v](const auto& newValue){ v = newValue;};
...
resetV({1,2,3}); // !!!
Things to Remember