14700

[code]

    class my_vector
        : private std::vector<int>
    {
        template <std::size_t... Index>
        void func_1_(std::index_sequence<Index...>)
        {
            int n[] = { 0, (static_cast<void>(push_back(Index)), 0)... };
        }
        template <std::size_t... Index>
        void func_2_(std::index_sequence<Index...>)
        {
            [](auto&&...){}((static_cast<void>(push_back(Index)), 0)...);
        }
    public:
        template <std::size_t N>
        void func_1()
        {
            func_1_(std::make_index_sequence<N>{});
        }
        template <std::size_t N>
        void func_2()
        {
            func_2_(std::make_index_sequence<N>{});
        }
    
        using std::vector<int>::begin;
        using std::vector<int>::end;
        using std::vector<int>::clear;
    };
    
[/code]

  

[code]

    int main()
    {
        my_vector v;
        for(auto& i : v)
        {
            std::cout << i;
        }
    
        v.func_1<10>();
        for(auto& i : v)
        {
            std::cout << i;
        }
        std::cout << std::endl;
    
        v.clear();
        for(auto& i : v)
        {
            std::cout << i;
        }
    
        v.func_2<10>();
        for(auto& i : v)
        {
            std::cout << i;
        }
        std::cout << std::endl;
    }
    
[/code]

このように出力されました。

> 0123456789  
>  9876543210

こう出力されると想定していました。

> 0123456789  
>  0123456789

どうして2行目の出力がそうなるのか教えて欲しいです。


CC BY-SA 3.0
2015-08-21T07:24:27.060
14699
2015-08-23T13:55:19.030
2015-08-21T10:32:33.820
10455
11012
question
c++
可変長テンプレートの展開と引数の評価順序についての疑問。

[code]

    void func_2_(std::index_sequence<Index...>)
    {
        [](auto&&...){}((static_cast<void>(push_back(Index)), 0)...);
    }
    
[/code]

このラムダ関数について、ちょっと説明します。

関数の引数がどんな順番で評価 (計算) されるかは、C++
の言語仕様上、未規程です。つまりコンパイラは、好き勝手な順番で引数を評価してもいいのです。有名な問題ですが、

[code]

    int i = 0;
    f(++i, ++i, ++i);
    
[/code]

で、関数 f に渡される引数の値はどうなるでしょうか。答えは、分からない、です。前から評価して (1, 2, 3)
になるかもしれない。前置インクリメントなので、最初にまとめて計算して (3, 3, 3)
になるかもしれない。同じコンパイラを使っていても、最適化の都合で、毎回違う順番に評価されるかもしれない。

ラムダ関数でも同じで、どんな順番に引数が評価されるかは分かりません。今回のコードでは、10個の コンマ式
`(static_cast<void>(push_back(Index)), 0)` が引数として渡されるわけですが、このコンマ式がどの順番で評価 (=
中の `push_back` がどの順番で実行) されるかは分かりません。まったくでたらめな順番でもいいのです。

ほとんどの処理系では、デフォルトでは引数を後ろからスタックに積みます。おそらく、コンパイラが引数をスタックに一つずつ積む毎に評価したので、順番が逆転したのでしょう。


CC BY-SA 3.0
2015-08-21T09:07:53.127
14700
2015-08-23T13:55:19.030
2015-08-23T13:55:19.030
3605
3605
14699
answer