2012-05-23 18 views
16

Varsayılan argümanları belirtmeden varsayılan argümanları alan bir işleve nasıl bağlanabilir ve sonra herhangi bir argüman olmadan arayabilir miyim?Varsayılan argümanları alan bir işleve bağlanıp sonra arayabilir miyim?

void foo(int a, int b = 23) { 
    std::cout << a << " " << b << std::endl; 
} 

int main() { 
    auto f = std::bind(foo, 23, 34); // works 
    f(); 


    auto g = std::bind(foo, 23); // doesn't work 
    g(); 

    using std::placeholders::_1; 
    auto h = std::bind(foo, 23, _1); // doesn't work either 
    h(); 

} 
+1

"Çalışmıyor" tanımını yapın. Değişkenlere farklı adlar verdiyseniz kod derler. –

+0

neden yeniden atama yapmayı sürdürüyorsunuz? – 111111

+0

@ R.MartinhoFernandes evet üzgünüm, örnek eksikti. Daha fazla sembolik bir ortalama olan – inf

cevap

20

Temel olarak, her zaman size foo(x) yazma derleyici foo(x, 23); olarak çevirir. Sadece işlev ismiyle doğrudan bir çağrınız varsa çalışır. Örneğin, işlevin imzası void(int, int) olduğundan &foo a void(*)(int) numarasına atayamazsınız. Varsayılan parametreler imzada hiçbir rol oynar. Ve onu bir void(*)(int, int) değişkenine atarsanız, varsayılan parametre hakkındaki bilgiler kaybolur: varsayılan değişkenden o değişkenle yararlanamazsınız. std::bind, bağırsaklarında bir yere bir void(*)(int, int) depolar ve böylece varsayılan parametre bilgilerini kaybeder.

Bir parametrenin varsayılan değerini işlevin dışından almak için C++ uygulamasında bir yol yoktur; bu nedenle, bağlandığınızda varsayılan değeri el ile sağlayarak takılırsınız.

+0

büyük arka plan güncellendi, teşekkürler. – inf

8

Bir lambda kullanarak istediğiniz davranışı taklit edebildiğinizi düşünüyorum.

auto g = [](){ foo(23); }; 

DÜZENLEME: Bu çizgisinde

şey sadece kontrol ve iyi çalışıyor görünüyor: http://ideone.com/SPSvi

0

Ben iki çözüm vardır:

1 - Sen (foo aşırı yüklenmeye neden olabilir) ve varsayılanı varsayılanı olarak adlandırın:

2 - Sen bağlama işleminde kullanabilirsiniz ardından varsayılan olarak statik bir değişken kullanabilir ve:

static int foo_default_b = 23; 
void foo(int a, int b = foo_default_b) 
{ 
    std::cout << a << " " << b << std::endl; 
} 

auto g = std::bind(foo, 23, foo_default_b); 
g(); 
0

This answer katılmıyor R. Martinho Fernandes' cevap. Sen gerçekten de varsayılan parametrelere bağlamak için boost::bind kullanabilirsiniz, sadece bu yüzden gibi içinde yer tutucular koymak gerekir: beklendiği gibi

boost::bind<void (int, int)>(foo, _1, _2)(12); 

Bu, foo(12, 23) arayacak. Bu özel kodu sınamamış olmama rağmen, yukarıdaki bağlantıya dayalı olarak kodumda benzer bir şey yaptım ve gcc 4.8.5'da çalışıyor.

Hmm, bunun sadece, boost::bind numarasını sorduğunu fark ettim. Varsa hangi farklılıklar olduğunu bilmiyorum.

İlgili konular