为什么在使用之前不初始化C ++ const模板化矢量?

收藏

为了个人方便,我创建了以下模板化向量const:

// shorthand for loops, etc.
template <size_t N>
const vector<size_t> range = []() {
    vector<size_t> res(N);
    for (size_t i = 0; i < N; i++) res[i] = i;
    cout << "Created range<" << N << ">: [";
    for (auto x: res) cout << x << ' ';
    cout << ']' << endl;
    return res;
}();

这样一来,我可以编写更多简洁的循环,如下所示:

for (auto i : range<42>) do_something(i);

However, I realised (after some debugging) that it seems to be not guaranteed that all required instantiations of range<N> are initialised before usage! This is rather counter-intuitive so I think if I am doing something wrong.

更准确地说,我具有以下MWE:

#include <bits/stdc++.h>
using namespace std;

template <size_t N>
const vector<size_t> range = []() {
    cout << "Initialising range<" << N << ">" << endl;
    vector<size_t> result(N);
    for (size_t i = 0; i < N; i++) result[i] = i;
    return result;
}();

template <size_t K>
class Data {
   private:
    size_t m_code;

   public:
    size_t get_code() const { return m_code; }

    constexpr static size_t cardinality = K + 1;

    explicit Data(size_t code);

    const static vector<Data> elems;
};

template <size_t K>
const vector<Data<K>> Data<K>::elems = []() {
    cout << "Creating Data elements for K=" << K << endl;
    vector<Data<K>> xs;
    for (size_t i : range<Data<K>::cardinality>) xs.push_back(Data<K>(i));
    return xs;
}();

template <size_t K>
Data<K>::Data(size_t code) {
    m_code = code;

    cout << "At the moment, range<" << K << "> is [";
    for (auto k : range<K>)
        cout << k << ' ';  // <<< Shouldn't range<K> be already initialised here?..
    cout << "] (len=" << range<K>.size() << ")" << endl;
}

int main() {
    cout << ">>> Inside main()" << endl;
    constexpr size_t K = 2;

    cout << "Data elements:" << endl;
    for (const auto &X : Data<K>::elems) {
        cout << "Element Data(" << X.get_code() << ")" << endl;
    }

    cout << "Now, range<" << K << "> is [";
    for (auto k : range<K>) cout << k << ' ';
    cout << "] (len=" << range<K>.size() << ")" << endl;
}

这将产生以下输出:

Initialising range<3>
Creating Data elements for K=2
At the moment, range<2> is [] (len=0)
At the moment, range<2> is [] (len=0)
At the moment, range<2> is [] (len=0)
Initialising range<2>
>>> Inside main()
Data elements:
Element Data(0)
Element Data(1)
Element Data(2)
Now, range<2> is [0 1 ] (len=2)

I don't really understand why it is working as it is. I mean, I would expect a const vector (or any vector!) to be initialised before it is used.

回复