2015-08-24 27 views
11

baktım böyle This case of template function overloading eludes my understandingGeçici olmayan işlevlerin aynı ad ve argümanlara sahip olmaları, ancak farklı dönüş türlerinin neden yasa dışıdır? (Ama şablon işlevleri için yasal?)

ve Function overloading by return type?

ama gibi birkaç ilişkili yığın taşması parçacığı ne tam aradığım cevabı bana vermek gibi görünüyor, en azından yorumlamak için kolay olan bir şekilde değil.

Sorum bu kadar aşağı kaynar: Bir tasarım ve teknik açıdan hem, neden yasal bunun için:

#include <iostream> 

using namespace std; 

template<class T> 
void func(){ 
    cout << "Compiler inferred from void return value!\n"; 
} 

template<class T> 
int func(){ 
    cout << "Compiler inferred from int return value!\n"; 
    return 0; 
} 

int main(){ 
    void (*thisFunc)()=func<int>; 
    int (*thatFunc)()=func<int>; 
    thisFunc(); 
    thatFunc(); 
} 

Ama bu:

#include <iostream> 

using namespace std; 

void func(){ 
    cout << "You won't see this because it won't compile!\n"; 
} 

int func(){ 
    cout << "Nor this one!\n"; 
    return 0; 
} 

int main(){ 
    void (*thisFunc)()=func; 
    int (*thatFunc)()=func; 
    thisFunc(); 
    thatFunc(); 
} 

Bu söz etmek gerekiyor Bu örnek, buFunc ve thatFunc başlatılırken rasgele bir şablon parametresini açıkça vermezseniz, ilk örnek derlenmeyecektir. İkisi arasındaki diğer tek fark, ilkinin tamamen maddi olmayan bir tiple templasyona uğramasıdır, çünkü görünüşe göre dönüş türüne aşırı yüklenmeme izin vermesidir. Derleyici, bu durumda, hangi fonksiyonun çağrılacağı konusunda bir çıkarımda bile bulunabiliyor, bu da fonksiyonun aşırı yüklenmesinin yasadışı olduğunu, C++ 'da geri dönüş tipine dönüştürebiliyor. Her durumda, sanırım temiz bir numara.

DÜZENLEME: Beni en çok rahatsız eden tutarsızlık olduğu şey: Ben gerçekten dönüş türüne göre aşırı kabul önce çok uzun ve sert düşünürdüm, ama dönüş türüne göre aşırı isteyen biri için "düzeltmek" eğer sadece anlamsız bir şablon parametresi eklemek veya görünüşte işlevlerin ad boşluklarının içine sarılmasıdır, o zaman ya C++ ya belirsiz olduğu düşünüldüğünde ya daha az ya da çok katı olmalıdır. Şablonların ve ad alanlarının doğru çalışması için bu işlevselliğe neden gereksinim duyduğunun zor bir nedeni var mı? Örneğin, örneğin benim örneğimde olduğu gibi kodları netleştirmek için şablonlara izin verilmediyse işe yaramayabilecek bir kod örneği var mı? Bir derleyici uyumluluk bakış açısı değil, bir dil tasarım bakış açısından rica ediyorum.

+0

Şablon için, SFINAE veya dönüş türüne izin vermeyi düşünüyorum. – Jarod42

+3

Gerçekten dönüş türünde aşırı yüklenme yapmıyorsunuz, ancak SFINAE kullanarak, her bir işlev işaretçisi için olası şablon örneğini seçin. 'Func 'seçeneğini kullandığınızda, her bir beyanda, ikamesinin çalıştığı tek bir şablon vardır, ancak diğerinin başarısız olması bir hata değildir. Sadece göz ardı edilir. –

cevap

11

Genel olarak geçersiz değil: Dönüş türünde şablon olmayan işlevleri aşırı yükleme yöntemi var. Yaptığın şey sadece geçersiz.

namespace A { 
    void func() {} 
} 
namespace B { 
    int func() { return 0; } 
} 
using A::func; 
using B::func; 
int main(){ 
    void (*thisFunc)()=func; 
    int (*thatFunc)()=func; 
    thisFunc(); 
    thatFunc(); 
} 

Bu, derler, bağlantılar ve çalışır. Bu geçerli olduğundan ve gerçek uygulamalar tarafından kabul edildiğinden, kodunuzun geçerli olmaması için teknik bir neden bulunmadığı açıkça belirtilmelidir. Kuşkusuz, tipik olarak, şablon olmayan işlevlerin, döndürülen adda dönüş türüne sahip olmadığından, bu, mangling adında bazı değişiklikler gerektirir, ancak kolayca yapılabilir.

Neyin ardında ne olduğu mantıklı bir nedendir: Geri dönüş türünde şablon olmayan işlevlerin aşırı yüklenmesi neredeyse kesinlikle bir hatadır. Bu işlev, normal bağlamlarda kararsız hale getirir, yaygın hatalar (bir yerde bir bildirimi değiştirmek ve başka bir yeri unutmak) için son derece zayıf bir tanılama sağlar, son derece sınırlı kullanımı vardır, bu yüzden bunu yapmayın.