2011-11-09 18 views
6

Büyük yapıların temsillerini oluşturmak için karma kullanıyorum, ancak yapıları üretim sırasında kopyalanıyor. Ben düşünün düşünmek zorundalar, bu yüzden nasıl önleneceğini merak ediyordum.Karma jeneratörler ile öznitelik kopyalarından kaçınmak

baskılar altında kısa örneği "Kopyala", hedef yapı rule::generate kopyalanan gibi: Ben referans olarak foo_rule 'ın niteliği bildirerek kopyasını durdurabilir

namespace karma = spirit::karma; 
namespace phoenix = boost::phoenix; 

struct foo 
{ 
    foo() { } 
    foo(foo const &other) { std::cout << "Copy!"; } 
    int f() const { return 42; } 
}; 

std::string output; 
typedef std::back_insert_iterator<std::string> iterator; 
karma::rule< iterator, foo() > foo_rule = 
    karma::int_[ karma::_1 = phoenix::bind(&foo::f, karma::_val) ]; 
foo my_foo; 
iterator it(output); 
karma::generate(it, foo_rule, my_foo); 

:

karma::rule< iterator, foo &() > foo_rule 

ama bu bir vektör ile çalışmaz [açıkçası foo s bu yüzden kopyalanabilir, ancak vektör inşaat kopyalamak için ucuz olabilir, ancak üretmek için zaman pahalı kopyalamak :-)]

Aşağıdaki örnek 'Kopyala!' Yazdırır. üretim sırasında beş kez (yani, vektör cetveli sırasında kopyaları göz ardı ederek);

std::vector<foo> my_vec_foo(5); 
karma::rule< iterator, std::vector<foo>() > vec_foo_rule = *foo_rule; 
karma::generate(it, vec_foo_rule, my_vec_foo); 

iki kural ile, olan VC 2008 tarihinde Boost 1.47 ile derleme değil referansları almak Having:

karma::rule< iterator, foo &() > foo_rule /* = ... */; 
karma::rule< iterator, std::vector<foo> &() > vec_foo_rule /* = ... */; 

alıyorum foo_rule 'ın nitelik başvuru değilse 10 kat halinde extract_from_container, Attribute = std::vector<foo> ve Exposed=std::vector<foo> & ile başlatılmıştır. Extract_from.hpp'nin 131'inci satırında, Exposed const &'u oluşturmaya çalışır ve referansa yeniden referans oluştururken derleyici başarısız olur.

Bir şeyleri özlüyorum gibi hissediyorum, bu yüzden herhangi bir işaretçi büyük takdir edilecektir!

+1

+1 mükemmel minimal sorun için kod ve çıktıda uyarı BÜYÜK MEKTUP bakın. Belki daha fazla kopya/pastable yapabilirdiniz (şu anda Ruh'un samimi bilgisi olmayan insanlar muhtemelen koşmayacaklardır). Cevabımı test ettim ve yazı tam bir minimum örnek içeriyor. Alkışlar – sehe

cevap

3

Eminim denediniz, ama yine de söyleyeceğim.

std::vector<foo> my_vec_foo(5); 
karma::rule< iterator, std::vector<foo>&() > vec_foo_rule = *foo_rule; 
karma::generate(it, vec_foo_rule, my_vec_foo); 

Güncelleme Sadece aşağıda pasajı (g ++ 4.6 Boost 1.47.0 ile) ile de denedim şu şekildedir: denedin. Yukarıdaki çalışmaların doğruluğunu teyit eder. Ancak, std::vector<foo> my_vec_foo(5)'un da 5 kopyasının gösterileceği gibi, karışıklık için bir oda var.

#include <boost/spirit/include/karma.hpp> 
#include <boost/spirit/include/phoenix.hpp> 

namespace karma = boost::spirit::karma; 
namespace phoenix = boost::phoenix; 

struct foo 
{ 
    foo() { } 
    foo(foo const &other) { std::cerr << "Copy!\n"; } 
    int f() const { return 42; } 
}; 

int main() 
{ 
    std::string output; 
    typedef std::back_insert_iterator<std::string> iterator; 
    iterator it(output); 
    karma::rule< iterator, foo&() > foo_rule = 
     karma::int_[ karma::_1 = phoenix::bind(&foo::f, karma::_val) ]; 

    foo my_foo; 
    karma::generate(it, foo_rule, my_foo); 

    std::vector<foo> my_vec_foo(5); 

    std::cerr << "\nSTART WATCHING NOW" << std::endl; 

    karma::rule< iterator, std::vector<foo>&() > vec_foo_rule = *foo_rule; 
    karma::generate(it, vec_foo_rule, my_vec_foo); 
} 

Çıktı:

Copy! 
Copy! 
Copy! 
Copy! 
Copy! 

START WATCHING NOW 
+0

Beş kopya net olmalı, çünkü yeniden boyutlandırma (ve özel ctor) nasıl çalışır. Varsayılan olarak, bir öğeyi ikinci parametre olarak maliyetlendirir ve bunları tüm ayrılmış yuvalara kopyalar. – Xeo

+0

@Xeo: Bunu açıklamalı mıyım? Açık olduğunu düşündüm :) – sehe

+0

Sadece merak edenler için bunu işaret etmek istedim. :) Ayrıca, örneğiniz bazı eksikleri özlüyor ve Ideone'da derlenmiyor gibi görünüyor. Kullandıkları Boost sürümü çok düşük görünüyor. – Xeo

İlgili konular