2015-03-15 22 views
6

std::back_insert_iteratorvoid eşit value_type sahip bir back_insert_iterator gelen kabın VALUE_TYPE çıkarmak için, ama aynı zamanda altında yatan Container bir işaretçi tutan bir protected elemanı container sahiptir. Ben bu satırlar boyunca, konteyner en value_type ayıklamak için bir özellikleri vardır sınıfını yazmaya çalışıyorum: Özellikleri sınıfı

Live Example

#include <iterator> 
#include <type_traits> 
#include <vector> 

template<class OutputIt> 
struct outit_vt 
: 
    OutputIt 
{ 
    using self_type = outit_vt<OutputIt>; 
    using value_type = typename std::remove_pointer_t<decltype(std::declval<self_type>().container)>::value_type; 
}; 

int main() 
{ 
    std::vector<int> v; 
    auto it = std::back_inserter(v); 
    static_assert(std::is_same<outit_vt<decltype(it)>::value_type, int>::value, ""); 
} 
Ancak bu (az ya da çok beklenildiği gibi) eksik tip hatalar karşılaşır. İçerisinde value_type'u çıkarmak için buralarda var mı?

+0

Neden yineleyici türetilmiş bir yuvalanmış tür kullanmıyorsunuz? [Canlı örnek] (http://coliru.stacked-crooked.com/a/3547c063ddfb1ddb) – dyp

+0

@dyp Ben çatıdaydım, 'back_insert_iterator' iç içe geçmiş bir typedef' container_type' bile var – TemplateRex

+0

Yakın zamanda eklenen canlı örnek. - Ooooh bu bir kamu üyesidir. Gördüğünüz gibi – dyp

cevap

6

o önsel açık değilken @Rapptz tarafından cevabın doğru ama jenerik kodu (yani bir ile bir fırsatlar olmadığını ham T* ya da back_insert_iterator ya da Standard Library'nin diğer çıktı yineleyicilerinden biri), daha sistematik bir yaklaşım gereklidir. Bu etki için, kullanıcı tanımlı bir namespace xstd sınıfında bir output_iterator_traits sınıf şablonunun tanımının altında.

#include <iterator>    // iterator, iterator_traits, input_iterator_tag, output_iterator_tag, random_access_iterator_tag 
           // back_insert_iterator, front_insert_iterator, insert_iterator, ostream_iterator, ostreambuf_iterator 
#include <memory>    // raw_storage_iterator 

namespace xstd { 

template<class T> 
struct output_iterator_traits 
: 
     std::iterator_traits<T> 
{}; 

template< class OutputIt, class T> 
struct output_iterator_traits<std::raw_storage_iterator<OutputIt, T>> 
: 
     std::iterator<std::output_iterator_tag, T> 
{}; 

template<class Container> 
struct output_iterator_traits<std::back_insert_iterator<Container>> 
: 
     std::iterator<std::output_iterator_tag, typename Container::value_type> 
{}; 

template<class Container> 
struct output_iterator_traits<std::front_insert_iterator<Container>> 
: 
     std::iterator<std::output_iterator_tag, typename Container::value_type> 
{}; 

template<class Container> 
struct output_iterator_traits<std::insert_iterator<Container>> 
: 
     std::iterator<std::output_iterator_tag, typename Container::value_type> 
{}; 

template <class T, class charT = char, class traits = std::char_traits<charT>> 
struct output_iterator_traits<std::ostream_iterator<T, charT, traits>> 
: 
     std::iterator<std::output_iterator_tag, T> 
{}; 

template <class charT, class traits = std::char_traits<charT>> 
struct output_iterator_traits<std::ostreambuf_iterator<charT, traits>> 
: 
     std::iterator<std::output_iterator_tag, charT> 
{}; 

} // namespace xstd 

unspecialized versiyonu sadece std::iterator_traits<T> devraldığı, ama <iterator> ve <memory> başlıklarda tanımlanan 6 çıkış yineleyiciler için, uzmanlık V yineleyici en operator=(const V&) bir argüman olarak görünen türüdür std::iterator<std::output_iterator_tag, V> devralır. uç yineleyicileri için

bu T ham depolama yineleyicileri için, typename Container::value_type karşılık gelir ve T ve charT için ostream ve ostreambuf yineleyicileri sırasıyla.

sonra transparantly çiğ işaretçiler ve Standart Kütüphane çıkış adım adım elde ikisi ile çalışacak formu

template<class InputIt, class OutputIt> 
auto my_fancy_algorithm(InputIt first, InputIt last, OutputIt dest) 
{ 
    using T = typename xstd::output_iterator_traits<OutputIt>::value_type; 
    for (; first != last; ++first) { 
     // ... construct arguments from *first 
     *dest++ = T{ /* arguments */ }; 
    } 
} 

bir jenerik algoritma.

2

sadece container_type kullanabilirsiniz sahip olduğunu:

#include <iterator> 
#include <type_traits> 
#include <vector> 

template<typename T> 
struct outit_v { 
    using container_type = typename T::container_type; 
    using value_type = typename container_type::value_type; 
}; 

int main() 
{ 
    std::vector<int> v; 
    auto it = std::back_inserter(v); 
    static_assert(std::is_same<outit_v<decltype(it)>::value_type, int>::value, ""); 
} 

Live Example