मुझे uninitialized_vector
कंटेनर बनाने में दिलचस्पी है, जो कि std::vector
के साथ समान रूप से समान होगा, जो नए तत्वों को अन्यथा बिना किसी तर्क-निर्माता कन्स्ट्रक्टर के बनाया जाएगा, इसके बिना बनाया जाएगा प्रारंभ। मैं मुख्य रूप से पीओडी को 0.
पर शुरू करने से बचने में रूचि रखता हूं, जहां तक मैं कह सकता हूं,
मानक कंटेनर में तत्वों के डिफ़ॉल्ट निर्माण से बचनेstd::vector
को एक विशेष प्रकार के आवंटक के साथ संयोजन करके इसे पूरा करने का कोई तरीका नहीं है।
मैं std::stack
, (, std::vector
मेरे मामले में) जो एक उपयोगकर्ता द्वारा प्रदान की कंटेनर adapts के रूप में ही नस में मेरी कंटेनर का निर्माण करना चाहते हैं। दूसरे शब्दों में, मैं std::vector
की पूरी तरह से पुन: कार्यान्वित करने से बचाना चाहता हूं और इसके बजाय इसके चारों ओर एक "मुखौटा" प्रदान करता हूं।
std::vector
के "बाहरी" से डिफ़ॉल्ट निर्माण को नियंत्रित करने का कोई आसान तरीका है?
यहाँ समाधान मैं, पर पहुंचे जो Kerrek के जवाब प्रेरित था है:
#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>
#include <cassert>
// uninitialized_allocator adapts a given base allocator
// uninitialized_allocator's behavior is equivalent to the base
// except for its no-argument construct function, which is a no-op
template<typename T, typename BaseAllocator = std::allocator<T>>
struct uninitialized_allocator
: BaseAllocator::template rebind<T>::other
{
typedef typename BaseAllocator::template rebind<T>::other super_t;
template<typename U>
struct rebind
{
typedef uninitialized_allocator<U, BaseAllocator> other;
};
// XXX for testing purposes
typename super_t::pointer allocate(typename super_t::size_type n)
{
auto result = super_t::allocate(n);
// fill result with 13 so we can check afterwards that
// the result was not default-constructed
std::fill(result, result + n, 13);
return result;
}
// catch default-construction
void construct(T *p)
{
// no-op
}
// forward everything else with at least one argument to the base
template<typename Arg1, typename... Args>
void construct(T* p, Arg1 &&arg1, Args&&... args)
{
super_t::construct(p, std::forward<Arg1>(arg1), std::forward<Args>(args)...);
}
};
namespace std
{
// XXX specialize allocator_traits
// this shouldn't be necessary, but clang++ 2.7 + libc++ has trouble
// recognizing that uninitialized_allocator<T> has a well-formed
// construct function
template<typename T>
struct allocator_traits<uninitialized_allocator<T> >
: std::allocator_traits<std::allocator<T>>
{
typedef uninitialized_allocator<T> allocator_type;
// for testing purposes, forward allocate through
static typename allocator_type::pointer allocate(allocator_type &a, typename allocator_type::size_type n)
{
return a.allocate(n);
}
template<typename... Args>
static void construct(allocator_type &a, T* ptr, Args&&... args)
{
a.construct(ptr, std::forward<Args>(args)...);
};
};
}
// uninitialized_vector is implemented by adapting an allocator and
// inheriting from std::vector
// a template alias would be another possiblity
// XXX does not compile with clang++ 2.9
//template<typename T, typename BaseAllocator>
//using uninitialized_vector = std::vector<T, uninitialized_allocator<T,BaseAllocator>>;
template<typename T, typename BaseAllocator = std::allocator<T>>
struct uninitialized_vector
: std::vector<T, uninitialized_allocator<T,BaseAllocator>>
{};
int main()
{
uninitialized_vector<int> vec;
vec.resize(10);
// everything should be 13
assert(std::count(vec.begin(), vec.end(), 13) == vec.size());
// copy construction should be preserved
vec.push_back(7);
assert(7 == vec.back());
return 0;
}
यह समाधान कैसे निकट एक विशेष विक्रेता की संकलक & एसटीएल के std::vector
कार्यान्वयन C++ 11 के अनुरूप है के आधार पर काम करेंगे।
क्या आप केवल एक डिफ़ॉल्ट निर्माता को परिभाषित कर सकते हैं जो कुछ भी नहीं करता? मैं शर्त लगाता हूं कि संकलक इनलाइन को ऑप्टिमाइज़ेशन के साथ इनलाइन कर सकता है या छोड़ सकता है। –
@ डॉग टी।- यह डिफॉल्ट कन्स्ट्रक्टर के मामले को हल कर सकता है, लेकिन रोचक सामग्री '' 'आकार''' में होने लगती है - यह स्पष्ट नहीं है कि कन्स्ट्रक्टरों का आविष्कार किए बिना' '' आकार बदलें 'जैसे कार्यों को कैसे कॉल किया जाए। –
@ डॉउग: इसमें चेतावनी है कि अब आप उपयोगकर्ता द्वारा परिभाषित कन्स्ट्रक्टर के साथ पीओडी नहीं हैं ... –