Aracılığıyla paylaş


enable_if Sınıf

SFINAE aşırı yükleme çözümlemesi için bir türün örneğini koşullu olarak oluşturur. İç içe typedefenable_if<Condition,Type>::type, ise ve yalnızca ise Condition için Typebir eş anlamlıdırtrue.

Sözdizimi

template <bool B, class T = void>
struct enable_if;

Parametreler

B
Sonuçta elde edilen türün varlığını belirleyen değer.

T
ise B örneği oluşturacak tür.true

Açıklamalar

ise B true, için enable_if<B, T> eş anlamlı olan "type" adlı iç içe bir tür tanımına Tsahiptir.

ise B false, enable_if<B, T> "type" adlı iç içe bir tür tanımına sahip değildir.

Bu diğer ad şablonu sağlanır:

template <bool B, class T = void>
using enable_if_t = typename enable_if<B,T>::type;

C++ dilinde şablon parametrelerinin değiştirme hatası kendi içinde bir hata değildir; bu SFINAE olarak adlandırılır (değiştirme hatası bir hata değildir). Genellikle, enable_if bir tanımın başka bir tanım yerine reddedilmesi için aşırı yükleme çözümlemesinden adayları kaldırmak için kullanılır; yani aşırı yükleme kümesini kaldırır. Bu, SFINAE davranışına uygundur. SFINAE hakkında daha fazla bilgi için bkz . Değiştirme hatası Wikipedia'da hata değil.

Dört örnek senaryo aşağıda verilmiştir:

  • Senaryo 1: bir işlevin dönüş türünü sarmalama:
    template <your_stuff>
typename enable_if<your_condition, your_return_type>::type
    yourfunction(args) {// ...
}
// The alias template makes it more concise:
    template <your_stuff>
enable_if_t<your_condition, your_return_type>
yourfunction(args) {// ...
}
  • Senaryo 2: Varsayılan bağımsız değişkeni olan bir işlev parametresi ekleme:
    template <your_stuff>
your_return_type_if_present
    yourfunction(args, enable_if_t<your condition, FOO> = BAR) {// ...
}
  • Senaryo 3: Varsayılan bağımsız değişkeni olan bir şablon parametresi ekleme:
    template <your_stuff, typename Dummy = enable_if_t<your_condition>>
rest_of_function_declaration_goes_here
  • Senaryo 4: İşlevinizin şablonlanmamış bir bağımsız değişkeni varsa, türünü sarmalayabilirsiniz:
    template <typename T>
void your_function(const T& t,
    enable_if_t<is_something<T>::value, const string&>
s) {// ...
}

Senaryo 1, dönüş türleri olmadığından oluşturucular ve dönüştürme işleçleriyle çalışmaz.

Senaryo 2 parametresini adsız bırakır. diyebilirsiniz ::type Dummy = BAR, ancak ad Dummy ilgisizdir ve bir ad vermek büyük olasılıkla "başvurulmayan parametre" uyarısı tetikleyebilir. bir FOO işlev parametresi türü ve BAR varsayılan bağımsız değişken seçmeniz gerekir. ve 0diyebilirsinizint, ancak kodunuzun kullanıcıları işleve yanlışlıkla yoksayılacak ek bir tamsayı geçirebilir. Bunun yerine ve 0 nullptr veya seçeneğini kullanmanızı void ** öneririz çünkü neredeyse hiçbir şey dönüştürülebilir void **değildir:

template <your_stuff>
your_return_type_if_present
yourfunction(args, typename enable_if<your_condition, void **>::type = nullptr) {// ...
}

Senaryo 2, sıradan oluşturucular için de çalışır. Ancak, ek parametreler alamadığı için dönüştürme işleçleri için çalışmaz. Ayrıca, oluşturucular için variadic de çalışmaz çünkü ek parametreler eklemek işlev parametre paketinin çıkarılmayan bir bağlam olmasını sağlar ve böylece amacını enable_ifyener.

Senaryo 3, adını Dummykullanır, ancak isteğe bağlıdır. Yalnızca " " typename = typename" işe yarayabilir, ancak bunun garip göründüğünü düşünüyorsanız "sahte" bir ad kullanabilirsiniz; işlev tanımında da kullanılabilecek bir ad kullanmayın. için bir tür enable_ifvermezseniz, varsayılan olarak geçersiz olur ve ne olduğu sizin için önemli Dummy olmadığından bu son derece mantıklıdır. Bu, dönüştürme işleçleri ve variadic oluşturucular da dahil olmak üzere her şey için çalışır.

Senaryo 4, dönüş türleri olmayan oluşturucularda çalışır ve böylece Senaryo 1'in sarmalama sınırlamasını çözer. Ancak, Senaryo 4 her zaman kullanılamayan şablonlanmamış işlev bağımsız değişkenleriyle sınırlıdır. (Şablonlu işlev bağımsız değişkeninde Senaryo 4 kullanıldığında, şablon bağımsız değişkeni kesintisi üzerinde çalışmayı engeller.)

enable_if güçlüdür, ancak kötüye kullanıldığında da tehlikelidir. Amacı aşırı yükleme çözümünden önce adayları yok etmek olduğundan, kötüye kullanıldığında etkileri çok kafa karıştırıcı olabilir. İşte birkaç öneri:

  • Derleme zamanında uygulamalar arasında seçim yapmak için kullanmayın enable_if . için bir tane yazmayın ve için başka bir tane enable_if CONDITION yazmayın !CONDITION. Bunun yerine, verilen yineleyicilerin güçlü yanlarına bağlı olarak uygulamaları seçen bir algoritma gibi bir etiket dağıtım deseni kullanın.

  • Gereksinimleri zorunlu kılmak için kullanmayın enable_if . Şablon parametrelerini doğrulamak istiyorsanız ve doğrulama başarısız olursa, başka bir uygulama seçmek yerine bir hataya neden olursa kullanın static_assert.

  • Aksi takdirde iyi kodu belirsiz hale getiren bir aşırı yükleme kümeniz olduğunda kullanın enable_if . Çoğu zaman, bu örtük olarak oluşturucuları dönüştürme sırasında oluşur.

Örnek

Bu örnekte, C++ Standart Kitaplığı şablon işlevinin std::make_pair() enable_ifavantajlarından nasıl yararlanır açıklanmaktadır.

void func(const pair<int, int>&);

void func(const pair<string, string>&);

func(make_pair("foo", "bar"));

Bu örnekte, make_pair("foo", "bar") döndürür pair<const char *, const char *>. Aşırı yükleme çözümlemesi, hangisini func() istediğinizi belirlemeli. pair<A, B> ' den pair<X, Y>örtük olarak dönüştüren bir oluşturucuya sahiptir. Bu yeni bir şey değil; C++98 sürümündeydi. Ancak, C++98/03'te, örtük olarak dönüştüren oluşturucunun imzası, olsa bile pair<int, int>(const pair<const char *, const char *>&)her zaman vardır. Aşırı yükleme çözümlemesi, bu oluşturucunun örneğini oluşturma girişiminin, örtük olarak dönüştürülebilir intolmadığından korkunç bir şekilde const char * patlamasına dikkat etmez; işlev tanımlarının örneği başlatılmadan önce yalnızca imzalara bakar. Bu nedenle, hem hem de pair<int, int> pair<string, string>'ye dönüştürmek pair<const char *, const char *> için imzalar mevcut olduğundan örnek kod belirsizdir.

C++11, yalnızca örtük olarak dönüştürülebilir olduğunda ve const Y& örtük olarak dönüştürülebilir olduğunda const X& var olduğundan emin olmak pair<A, B>(const pair<X, Y>&) için BA kullanarak enable_if bu belirsizliği çözdü. Bu, aşırı yükleme çözümlemesinin dönüştürülebilir pair<const char *, const char *> pair<int, int> olmadığını ve aldığı pair<string, string> aşırı yüklemenin uygulanabilir olduğunu belirlemesine olanak tanır.

Gereksinimler

Üstbilgi: <type_traits>

Ad alanı: std

Ayrıca bkz.

<type_traits>