2017-01-20 18 views
6

Bir işlev için "kullanma" nasıl kullanılır?Bir işlev için "kullanma" nasıl kullanılır?

void (*Bf)(int) = f; 

ya da sadece bir fonksiyon içine:

void Bf(int i) { f(i); } 

Muhtemelen tercih Örneğin

class A; 
void f(int); 

struct B 
{ 
    using BA = A; 
    using Bf = f; ??? 
}; 
+0

http://en.cppreference.com/w/cpp/language/using_declaration –

cevap

11

Sen

struct B 
{ 
    using BA = A; 
    constexpr static auto Bf = f; 
} 

sen can sıkıcı olabilir türünü belirtme konusunda endişelenmeniz gerekmez Bu şekilde yapabilirsiniz.

Statik olmayan bir değişken bildirmek istemezsiniz, aksi takdirde nesnenizin her bir kopyası bir işlev işaretçisini taşır. Ayrıca, bunun değişebilir olmasını da istemiyorsunuz, çünkü o zaman onu yeniden atayabilirsiniz. Ayrıca, çalışma zamanında potansiyel olarak belirlenmesini istemiyorsunuz çünkü o zaman, derleyici, Bf numaralı çağrıya gerçekten f numaralı çağrıyı çağırdığı veya başka bir deyişle işlev dolaylı ödeme maliyetlerini ödeyeceği belirli bir bağlamda kendini kanıtlamak zorunda kalacak. constexpr, bu son iki noktayı ele alır.

+0

TBH'nin herhangi bir iyi düzenleyici, basit bir işlev işaretçisinin bir kez sabit bir ifadeyle başlatıldığı ve daha sonra yazılmadığı konusunda yardım edebilir. SSA yaparken bunu ücretsiz olarak hemen alırsınız. – MSalters

+0

@MSalters Bu gibi ifadeleri her zaman görüyorum ve neredeyse her zaman yanılıyorlar. Dengede, derleyicinin bir işlev işaretçisini satır içi göstermesi çok nadirdir. https://godbolt.org/g/mBMZeF. Statik bir değişken temel olarak bir globaldir ve eğer değişebilirse herhangi bir zamanda herhangi bir zamanda değişebilir. Bu nedenle, önemsiz olmayan programlar için uygun olmayan tüm program analizi olmadan satır içi hukuki bir kural değildir. Bir örnek değişkeni ile, üye işlev işaretçisi çağıran işlev, örneğin oluşturulduğu yere tam olarak çizilirse işe yarayabilir. Öyleyse büyük bir şey. –

+0

Globals (ve sınıf statiği) ile ilgili problem, SSA'nın neredeyse imkansız olduğu ve kabaca belirtmiş olmanızdır. SSA sadece tüm yazıların görünürlüğünü değil, aynı zamanda siparişlerini de gerektirir. Bu yüzden, globals optimize ediciler için basit değildir. Ama bu, tüm globals'ların bir özelliği ve küresel işlev göstergelerine özgü değil. – MSalters

2

f Eğer sadece bir fonksiyondur, üye işlev işaretçisi ekleyebilirsiniz ya Bununla birlikte, B'a fazla üye eklemekten kaçınıyor. f bir işlev şablonu ise


, sadece takma, ona iletmek gerekiyordu edemez: evet ...

template <class... Args> 
auto Bf(Args&&... args) 
    -> decltype(::f(std::forward<Args>(args)...)) 
    noexcept(noexcept(::f(std::forward<Args>(args...)))) 
{ 
    return ::f(std::forward<Args>(args)...); 
} 

olan.

+2

Herhangi bir neden 'oto Bf = f; 'bir olasılık değil mi? – Rakete1111

+1

Bunun iyi bir çözüm olduğunu düşünmüyorum, 'B' nin her bir örneği, bir işlev işaretçisine sahip olacak, boyutunu şişirecek. Ve hatta yeniden atanabilir. Kullanıcı başlangıç ​​bildirimi olarak '' ifadesini '' kullandığı için, tüm örnekler ve değişmezler için aynı olmakla açıkça anlaşılır. –

+0

@Rakete Kötü biçimlendirilmiş olduğundan. – Barry

2

Nir Friedman's answer mükemmeldir, ancak f'un aşırı yüklü olması durumunda çalışmayacaktır. C++ 14

Eğer a generic lambda ile bunun için bir çözüm olabilir:

struct B { 
    using BA = A; 
    static constexpr auto BF = [](auto&&... args) { 
    return f(std::forward<decltype(args)>(args)...); 
    }; 
}; 

o sırf std::forward 'ın ayrıntı ise biraz complicat görünüyorsa. Ben daha basit kavramak yapmak std::forward olmadan gösterecektir (ancak f params olarak referans tipleri vardır eğer başarısız olur bu kullanmayın):

struct B { 
    using BA = A; 
    static constexpr auto BF = [](auto... args) { return f(args...); }; 
}; 
0

fark Af ise sadece bir tür olmasıdır gerçek bir işlevdir. Eğer tipf itibariyle Bf tanımlamak için using kullanmak istiyorsanız, o zaman kullanın:

using Bf = decltype(f); 
+0

Bunun bir yorum olduğunu söyleyebilirim. – HolyBlackCat

İlgili konular