0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【tips】いまさらautoキーワード

Last updated at Posted at 2024-04-14

備忘録です

(どのサイトにも似たような説明が書かれているので、詳細は省きます)
(結果はバージョンやコンパイラーによって変わる場合があります)

autoが記述できる場所

.cpp
#include <iostream>
auto f1() { return 1; }			//戻り値型
int f2(auto a) { return a; }	//引数型
auto f3(int a) -> int { return a; }		//後置戻り値型のプレースホルダ
auto f4(int a) -> auto { return a; }	//後置戻り値型

//f5(),f6()関数の引数が1の場合、
//f5()関数はintが戻り値型となる
//f6()関数はconst int&が戻り値型となる(decltype(auto)の効果)
auto f5(const auto& a) { return a; }
decltype(auto) f6(const auto& a) { return a; }

auto f7 = [](auto a) { return a; };		//ラムダ式の戻り値型と引数型

template<auto T> class A { };	//テンプレートパラメータ
class B {
    static inline auto m1 = 1;  //OK(staticの場合はautoで変数定義できる)
    //auto m2 = 2;    //コンパイルエラー(メンバー変数はautoで定義できない)
};

int main()
{
	int z = 1;

    //auto a;	//コンパイルエラー(必ず初期値が必要)
    auto b = 1;	//変数
    decltype(auto) c = z + 1;	//右辺の z + 1 がautoの式として使われる
                                //decltype(z + 1) c = z + 1; //と同じ結果
    int* d = new auto(1);		//int* d = new int(1) と同じ結果
    delete d;

    static_assert(std::is_same<decltype(f5(1)), int>::value, "");
    static_assert(std::is_same<decltype(f6(1)), const int&>::value, "");

    for(auto i = 0; i<3; i++) { std::cout << i << std::endl; }
    switch (auto i = f2(99)) {
    case 99: std::cout << i << std::endl; break;
    default: break;
    }
    while(auto i = 'c') { std::cout << i << std::endl; break; }
    //std::cout << i << std::endl;    //コンパイルエラー(当然、ブロック外ではi変数は参照できない)
}

auto と decltype(auto) の違い

.cpp
#include <type_traits>
int main()
{
    int z = 1;

    auto a = 1;
    auto b = (const int) 1;
    auto c = (int*) &z;
    auto d = (const int*) &z;
    auto e = (int&) z;
    auto f = (const int&) 1;
    auto g = (int&&) 1;
    auto h = (const int&&) 1;

    //int*はポインタなので*が残るのは当然
    //const int*はz変数の値を参照してるのでconstは残る
    //const int,int&およびint&&は複製されるのでconstは外れる
    static_assert(std::is_same<decltype(a), int>::value, "");
    static_assert(std::is_same<decltype(b), int>::value, "");
    static_assert(std::is_same<decltype(c), int*>::value, "");
    static_assert(std::is_same<decltype(d), const int*>::value, "");	//constは残る
    static_assert(std::is_same<decltype(e), int>::value, "");
    static_assert(std::is_same<decltype(f), int>::value, "");
    static_assert(std::is_same<decltype(g), int>::value, "");
    static_assert(std::is_same<decltype(h), int>::value, "");

    a = 10;
    b = 10;
    *c = 10;
    //*d = 10; //constなので当然コンパイルエラー
    e = 10;
    f = 10;
    g = 10;
    h = 10;

    //-----------------------
    //-----------------------
    decltype(auto) o = 1;
    decltype(auto) p = (const int) 1;
    decltype(auto) q = (int*) &z;
    decltype(auto) r = (const int*) &z;
    decltype(auto) s = (int&) z;
    decltype(auto) t = (const int&) 1;
    decltype(auto) u = (int&&) 1;
    decltype(auto) v = (const int&&) 1;

    //p変数は複製されるのでconstが外れる
    //r,t,v変数は参照なのでconstは残る
    static_assert(std::is_same<decltype(o), int>::value, "");
    static_assert(std::is_same<decltype(p), int>::value, "");   //constが外れる
    static_assert(std::is_same<decltype(q), int*>::value, "");
    static_assert(std::is_same<decltype(r), const int*>::value, "");
    static_assert(std::is_same<decltype(s), int&>::value, "");
    static_assert(std::is_same<decltype(t), const int&>::value, "");
    static_assert(std::is_same<decltype(u), int&&>::value, "");
    static_assert(std::is_same<decltype(v), const int&&>::value, "");

    o = 10;
    p = 10;
    *q = 10;
    //*r = 10;      //const
    s = 10;
    //t = 10;		//const
    u = 10;
    //v = 10;		//const

    //volatile(C++20より不正確は非推奨), register(C++11より非推奨)の調査は割愛する
}

const,*,&,&&での修飾

.cpp
#include <type_traits>
int main()
{
    int z = 1;

    const auto* a1 = &z;	//autoの前後は修飾できる
    const auto& a2 = z;
    const auto&& a3 = 1;

    auto&& a4 = 1;    //auto&&には特別な機能があり、左辺値を代入
    auto&& a5 = z;    //した場合、左辺値参照になる(a5変数はint&型)

    auto b1 = &z;			//*で修飾してもしなくても結果は一緒
    auto* b2 = &z;
    *b1 = 10;
    *b2 = 11;
    static_assert(std::is_same<decltype(b1), int*>::value, "");
    static_assert(std::is_same<decltype(b2), int*>::value, "");

    const auto c1 = &z;		//constを付けてる場合、微妙に結果が違う
    const auto* c2 = &z;
    *c1 = 12;		//※なぜか変更できる(constが無効になっている)
    //*c2 = 13;     //constを付けてるので変更できなくて当然
    //static_assert(std::is_same<decltype(c1), int*>::value, "");		//c1変数の型がint*でも
    //static_assert(std::is_same<decltype(c1), const int*>::value, "");	//const int*でもない(不明な型)
    static_assert(std::is_same<decltype(c2), const int*>::value, "");

    //-----------------------
    //-----------------------
    const decltype(auto) d1 = 1;    //decltype(auto)の前にconstを付けられる
    //decltype(auto*) d2 = &z; 		//コンパイルエラー(decltype(auto)の後に*,&,&&は付けられない)
    //decltype(auto&) d3 = z;
    //decltype(auto&&) d4 = 1;
    //decltype(auto)* d5 = &z;
    //decltype(auto)& d6 = z;
    //decltype(auto)&& d7 = 1;
}

参照URL

auto
通常関数の戻り値型推論
decltype(auto)
後置戻り値型をプレースホルダーにすることを許可
ジェネリックラムダ
非型テンプレートパラメータのauto宣言
autoパラメータによる関数テンプレートの簡易定義

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?