2011-11-25 18 views
6

Mükemmel yönlendirme ile ilgili bazı zorluklarım var.Mükemmel yönlendirme ve std :: tuple (veya diğer şablonlu sınıf)

Şu anki anlayış düzeyim: tutkal Şablon + rvalue reference + std :: forward ve özel büyülü mod, şablon kesinti kurallarının her zamankiyle aynı anlama gelmediği durumlarda etkinleştirilir, ancak mükemmel bir yönlendirmeye izin vermek için hazırlanmışlardır. Örnek:

template <typename T> 
void outer(T&& t) 
{ 
    inner(std::forward<T>(t)); // perfect forwarding activated 
} 
Ancak, T aslında aslında şablonlu bir sınıfsa ne olur? Örneğin, bir std :: tuple'ı nasıl mükemmelleştirebilirim? Eğer bir T & & 'yu kullanırsanız, tuple'da yer alan nesnelerin tüm tip bilgilerini kaybedeceğim.
Aşağıdaki kod çalışamaz Ancak:

template <typename... Args> 
void outer(std::tuple<Args...>&& t) 
{ 
    inner(std::forward<std::tuple<Args...>>(t)); 
    use_args_types_for_something_else<Args...>(); // I need to have Args available 
} 

int main() 
{ 
    std::tuple<int, double, float> t(4, 5.0, 4.0f); 
    outer(t); 
} 

Son gcc anlık diyor ki:

error: cannot bind 'std::tuple<int, double, float> lvalue to 
std::tuple<int, double, float>&& 

Yani açıkça, biz genel, şablon olmayan durumda hala nerede lvalue bağlama olamaz referansı değiştirmek için. "Mükemmel forwading modu"

yüzden sinsi ve bir şablon şablon olarak benim demet kullanmak çalıştı aktif değildir:

template < 
    typename... Args 
    template <typename...> class T 
> 
void outer(T<Args...>&& t) 
{ 
    inner(std::forward<T<Args...>>(t)); 
    use_args_type_for_something_else<Args...>(); 
} 

Ama hala aynı hatayı alıyorum. çünkü öyle

template <typename T> 
void outer(T&& t) 
{ 
    inner(std::forward<T>(t)); // perfect forwarding activated 
} 

yukarıdaki eser: parametrenin tipi fonksiyonu için bir şablon türü olduğundan, mükemmel yönlendirme ulaşmanın tek yolu, ilk örnekteki gibi yalnızca

+0

Türü belirtmeden std :: forward öğesini çağıramıyorsunuz (şablon işlevi olduğundan ve kesinti yapabilir)? std :: forward (t) ' – SoapBox

cevap

3

Mükemmel yönlendirme işleri T'un SomeType& veya SomeType&& olarak çıkarıldığı özel bir durum. Bununla birlikte, bu durum, tuple elemanları için tip bilgisinin iyi olduğu anlamına gelmez anlamına gelmez. Hala geri alınabilir (değişken bir şablon paketini yazabileceğinizi düşünmüyorum).

template <class T> 
struct call_uses_args; 

template <class ...Args> 
struct call_uses_args<std::tuple<Args...>> 
{ 
    void call() const { use_args_types_for_something_else<Args...>(); } 
}; 

template <typename TupleT> 
void outer(TupleT&& t) 
{ 
    inner(std::forward<TupleT>(t)); 
    call_uses_args<typename std::remove_reference<TupleT>::type>().call(); 
} 

olsa hiçbir iyi bir genel çözüm olabilir, ama umarım böyle durumlar nadirdir: Örneğin, yine böyle use_args_types_for_something_else çağırabilir. (E.g, bu özel örnekte, yalnızca outer'u aşırı yüklemesi daha basit olabilir.)

+0

Güzel ve hassas cevabınız için teşekkür ederiz. Bu yüzden, C++ 11'deki mükemmel yönlendirme ile ilgili olarak, bu garip combo "template + rref + std :: forward" üzerinde bu kadar çok güvendiğini hala biraz rahatsız ediyorum. Genel kuralların ("SADECE GERİ ÖDEME'ye rumuz referansları" gibi) ufak bir nokta yaratması artık geçerli değildir. Mükemmel yönlendirme için bazı özel sözdizimi C++ 11 için daha iyi olmaz mı diye merak ediyorum. Her halükarda, bu durumda bir çözümün, 'dış' için iki aşırı yüklenme yapmak mümkün olduğu için bir anlaşma büyüklüğü değil, biri const ref ve bir tanesi de PF'ye öykünmek için rref olması doğrudur. –