Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<blockquote> <p>Is it possible to implement a std::array-like container (a thin wrapper around a built-in C array) with a C++0x initializer_list?</p> </blockquote> <p><strike><strong>Yes</strong>, well, so long as you are willing to cheat.</strike> As Mooing Duck points out, no, not even cheating, <a href="http://www.velocityreviews.com/forums/t728955-c-0x-exact-semantics-of-initializer_list-e.html" rel="nofollow">unless the compiler implementors let you</a>. Though, it is still possible to get close enough -- it is possible to use initializer lists and a static array that is hidden by the wrapper. </p> <p>This is some code I wrote for my personal toolbox. The key is to disregard the size altogether, even for the array, and let the provider container handle it; in this case, <code>initializer_list</code> who can provide the size via <code>std::distance</code>, thus avoiding client-side size explicitation (a term that I just invented, it seems). </p> <p>Since it is the "anyone could've come up with it" kind of code, no problems about providing it "back" to the public; in fact, I got the idea from some expert guy whose nick I don't remember at Freenode's <code>##c++</code> channel, so I guess the recognition is for them:</p> <p>*<em>EDIT</em>*ed:</p> <pre><code>template &lt;typename T&gt; struct carray { // typedefs for iterator. The best seems to be to use std::iterator&lt;std::random_iterator_tag,T,int&gt; here ... template &lt;size_t N&gt; explicit carray (T (&amp;arr)[N]) : ax(arr), sx(N) {} // note the linked article. // This works *only* if the compiler implementor lets you. carray (std::initializer_list&lt;T&gt; X) : ax (X.begin()), sx(std::distance(X.begin(),X.end()) {} // YMMV about the rest of the "rule of N": // no copy constructor needed -- trivial // no destructor needed -- data outscopes the wrapper // no assignment operator needed -- trivial // container functions, like begin(), end(), size()... private: T* ax; size_t const sx; }; </code></pre> <p>Usage and declaration in C++0x mode is pretty simple (just tested with GCC 4.6 in Fedora 15), but it works with the caveats noted in the external links above, so it is apparently undefined behaviour:</p> <pre><code>using lpp::carray; carray&lt;short const&gt; CS = {1, -7, 4, 188}; </code></pre> <p>However, I don't see <em>why</em> a compiler implementor would not implement an initializer_list of integrals as a static array anyway. Your call.</p> <p>Not only it works like that, provided you can <code>#ifdef</code> the initializer constructor out of the way in pre-C++0x mode, you can actually use this in pre-C++0x; although predeclaration of the data array as its own variable will be needed, it is IMHO the closest it gets to the original intent (and it has the advantage of being usable and not causing eg.: scope issues). (also tested with the above compiler, plus Debian Wheezy's GCC):</p> <pre><code>using lpp::carray; short data[]= {1, -7, 4, 188}; carray&lt;short const&gt; CS (data); </code></pre> <p><em><strong>There!</em></strong> No "size" parameter <em>anywhere</em>!</p> <blockquote> <p>We would also want to provide a constructor to specify the size if an initializer list was not provided. </p> </blockquote> <p>Sorry, this is one feature I have not maganed to implement. The problem is how to assign the memory "statically" from an outside source, perhaps an Allocator. Assuming it could be done somehow via a helper functor <code>allocate</code>, then the constructor would be something like this:</p> <pre><code>explicit carray (size_t N) : ax(allocate(N)), sx(N) {} </code></pre> <p>I hope this code is of help, as I see the question is more or less old.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload