0Pricing
C++ Academy · Ders

SFINAE

İşlevleri koşullu olarak etkinleştirin

SFINAE, CoddyKit'te ücretsiz bir C++ Academy dersidir. Bu, 4 dersinin 3. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, C++ Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. C++ Academy kursu toplamda 4 dersten oluşur.

SFINAE Ne Anlama Gelir

SFINAE, "Substitution Failure Is Not An Error" ifadesinin kısaltmasıdır. Derleyici şablon bağımsız değişkenlerini yerine koyduğunda sonuç hatalı biçimlenmişse bu aday, ciddi bir hataya yol açmak yerine yalnızca kaldırılır.

  • Koşullu aşırı yüklemeleri etkinleştirir.
  • Derleme zamanında seçimin temelini oluşturur.
#include <iostream>
#include <type_traits>

template <typename T>
typename std::enable_if<std::is_integral<T>::value, bool>::type
isOdd(T n) { return n % 2 != 0; }

int main() {
    std::cout << std::boolalpha << isOdd(3) << '\n';
    return 0;
}

Yerine Koyma Hatası Uygulamada

Bir türü yerine koymak işlevin imzasını geçersiz kılarsa derleyici bu işlevi sessizce atlar ve diğer adayları değerlendirmeye devam eder.

#include <iostream>

template <typename T>
auto sizeOfValue(T t) -> decltype(t.size()) { return t.size(); }

int main() {
    std::string s = "hello";
    std::cout << sizeOfValue(s) << '\n';
    return 0;
}

İki Aşırı Yükleme, Biri Kazanır

Belirli bir tür için tam olarak birinin başarıyla yerine konacağı iki aşırı yükleme sağlayın. SFINAE geçersiz olanı eler.

#include <iostream>
#include <type_traits>

template <typename T>
typename std::enable_if<std::is_integral<T>::value, const char*>::type
name() { return "integral"; }

template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, const char*>::type
name() { return "floating"; }

int main() {
    std::cout << name<int>() << ' ' << name<double>() << '\n';
    return 0;
}

decltype ve İfade SFINAE'si

Dönüş türündeki bir ifadeye decltype uygulamak, bir işlevin yalnızca o ifade tür için geçerliyse var olmasını sağlar.

#include <iostream>

template <typename T>
auto tryDouble(T x) -> decltype(x + x) { return x + x; }

int main() {
    std::cout << tryDouble(21) << '\n';
    std::cout << tryDouble(2.5) << '\n';
    return 0;
}

Üye Algılama

Klasik bir SFINAE tekniği, onu kullanan bir ifadenin derlenip derlenmediğini kontrol ederek bir türün belirli bir üyeye sahip olup olmadığını algılar.

#include <iostream>
#include <type_traits>
#include <vector>

template <typename T>
auto hasSize(int) -> decltype(std::declval<T>().size(), std::true_type{});

template <typename T>
std::false_type hasSize(...);

int main() {
    std::cout << std::boolalpha;
    std::cout << decltype(hasSize<std::vector<int>>(0))::value << '\n';
    std::cout << decltype(hasSize<int>(0))::value << '\n';
    return 0;
}

... Geri Dönüşü

... alan bir aşırı yükleme (değişken sayıda bağımsız değişken), en düşük önceliğe sahiptir. SFINAE kısıtlı aşırı yükleme başarısız olduğunda tüm durumları karşılayan seçenek olarak görev yapar.

#include <iostream>

template <typename T>
auto pick(int) -> decltype(T{}.value, void()) { std::cout << "has value\n"; }

template <typename T>
void pick(...) { std::cout << "no value\n"; }

struct WithValue { int value = 0; };

int main() {
    pick<WithValue>(0);
    pick<int>(0);
    return 0;
}

void_t

C++17'nin std::void_t özelliği algılamayı basitleştirir: düzgün biçimlenmiş tüm türleri void türüne eşler; böylece bir özelleştirme yalnızca denetlenen ifade geçerliyse etkinleşir.

#include <iostream>
#include <type_traits>
#include <vector>

template <typename T, typename = void>
struct HasSize : std::false_type {};

template <typename T>
struct HasSize<T, std::void_t<decltype(std::declval<T>().size())>> : std::true_type {};

int main() {
    std::cout << std::boolalpha;
    std::cout << HasSize<std::vector<int>>::value << '\n';
    std::cout << HasSize<int>::value << '\n';
    return 0;
}

Neden Doğrudan Hata Vermiyor

SFINAE olmadan geçersiz bir yerine koyma ciddi bir derleme hatası olur ve bu durumdan kurtarılamazdı. SFINAE bunu sessizce "aday değil" durumuna dönüştürür.

#include <iostream>
#include <type_traits>

template <typename T>
typename std::enable_if<std::is_pointer<T>::value, bool>::type
isNull(T p) { return p == nullptr; }

int main() {
    int x = 0;
    std::cout << std::boolalpha << isNull(&x) << '\n';
    return 0;
}

Etiket Dağıtımı Seçeneği

SFINAE'nin okunması zor olabilir. Etiket dağıtımı bunun yerine küçük etiket türleri ve aşırı yük çözümlemesi kullanarak bir uygulama seçer.

#include <iostream>
#include <type_traits>

template <typename T>
void impl(T v, std::true_type) { std::cout << "integral: " << v << '\n'; }

template <typename T>
void impl(T v, std::false_type) { std::cout << "other: " << v << '\n'; }

template <typename T>
void handle(T v) { impl(v, std::is_integral<T>{}); }

int main() {
    handle(5);
    handle(2.5);
    return 0;
}

SFINAE ve constexpr if

C++17'de if constexpr, tek bir işlev içindeki dallanma için çoğu zaman SFINAE'nin yerini alır; çünkü kullanılmayan dallar derleme zamanında elenir.

#include <iostream>
#include <type_traits>

template <typename T>
void describe(T v) {
    if constexpr (std::is_integral<T>::value) {
        std::cout << "integral: " << v << '\n';
    } else {
        std::cout << "other: " << v << '\n';
    }
}

int main() {
    describe(7);
    describe(3.14);
    return 0;
}

Hepsini Bir Araya Getirme

SFINAE, aşırı yükleme düzeyinde tür özelliklerine göre ayrı işlev şablonları arasında seçim yapmanız gerektiğinde büyük yarar sağlar.

#include <iostream>
#include <type_traits>

template <typename T>
typename std::enable_if<std::is_signed<T>::value, T>::type
absValue(T v) { return v < 0 ? -v : v; }

int main() {
    std::cout << absValue(-9) << '\n';
    return 0;
}

Kısa Kontrol

SFINAE'yi anlayıp anlamadığınızı test edin.

Özet

SFINAE'yi öğrendiniz:

  • geçersiz bir yerine koyma hata vermek yerine adayı kaldırır
  • işlevleri koşullu olarak etkinleştirmek için enable_if, decltype ve void_t ile kullanılır
  • ... aşırı yüklemesi geri dönüş seçeneği olarak görev yapar
  • modern seçenekler arasında etiket dağıtımı ve if constexpr bulunur

Sırada klasik enable_if kalıplarına ayrıntılı olarak odaklanacaksınız.

Sıkça Sorulan Sorular

“SFINAE” dersi ücretsiz mi?

Evet — “SFINAE” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve C++ Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. C++ Academy kursu toplamda 4 dersten oluşur.

“SFINAE” dersinde ne öğreneceğim?

İşlevleri koşullu olarak etkinleştirin C++ Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

C++ Academy öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te C++ Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 3. dersidir.

“SFINAE” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu C++ Academy dersinde kod yazıp çalıştırabilir miyim?

Evet. Her C++ Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. Tam Özelleştirme
  2. Kısmi Özelleştirme
  3. SFINAE
  4. enable_if Örüntüleri
← C++ Academy Sayfasına Dön