enable_if – třída
Podmíněně vytvoří instanci typu SFINAE rozlišení přetěžování.Vnořené definice typedef enable_if<Condition,Type>::type existuje, a je synonymum pro Type, a pouze v případě Condition je true.
template<bool B, class T = void>
struct enable_if;
Parametry
B
Hodnota, která určuje výsledný typ existence.T
Typ instance, pokud B je true.
Poznámky
Pokud B je true, enable_if<B, T> obsahuje vnořené definice typu s názvem "typ", je synonymum pro T.
Pokud B je false, enable_if<B, T> nemá vnořené definice typu s názvem "typ".
Tato šablona alias je k dispozici:
template< bool B, class T = void >
using enable_if_t = typename enable_if<B,T>::type;
V jazyce C++ selhání nahrazení parametrů šablon není chyba sama o sobě – to se nazývá SFINAE (náhrada selhání není chyba).Obvykle enable_if se používá k odstranění kandidátů z přetížení rozlišení –, je culls sadu přetížení – tak, že mohou být odmítnuty jednu definici ve prospěch jiného.Odpovídá chování SFINAE.Další informace o SFINAE naleznete v tématu náhrada selhání není chyba na Wikipedia.
Zde jsou čtyři scénáře příkladu:
Scénář 1: Obtékání návratový typ funkce:
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) { // ... }
Scénář 2: Přidání parametru funkce, která má výchozí argument.
template <your_stuff> your_return_type_if_present yourfunction(args, enable_if_t<your condition, FOO> = BAR) { // ... }
Scénář 3: Přidání parametr šablony, který obsahuje výchozí argument.
template <your_stuff, typename Dummy = enable_if_t<your_condition>> rest_of_function_declaration_goes_here
Scénář 4: Pokud má vaše funkce bez použití šablon argument, může obtékat jeho typ:
template <typename T> void your_function(const T& t, enable_if_t<is_something<T>::value, const string&> s) { // ... }
Scénář 1 nefunguje s konstruktory a operátory převodu, protože nemají návratové typy.
Scénář 2 listy parametr nepojmenované.Řekněte ::type Dummy = BAR, ale název Dummy je irelevantní, a pod názvem mohou spustit na varování "na které neexistuje odkaz parametr".Je třeba zvolit FOO funkce typ parametru a BAR výchozí argument.Řekněte int a 0, ale pak uživatelé vašeho kódu může omylem předat funkci další celé číslo, které bude ignorována.Namísto toho doporučujeme použít void ** a 0 nebo nullptr vzhledem k tomu, že téměř nic není převést na void **:
template <your_stuff> your_return_type_if_present
yourfunction(args, typename enable_if<your_condition, void **>::type = nullptr) {
// ...
}
Scénář 2 lze použít také pro běžné konstruktory.Však nefunguje pro operátory převodů vzhledem k tomu, že se nemůžete provést dodatečné parametry.Také nefunguje pro variadic konstruktory protože přidání dodatečné parametry parametr funkce pack-odvozen kontext umožňuje a tím účinně chrání před cílem enable_if.
Scénář 3 používá název Dummy, ale je nepovinný.Právě "typename = typename" pracovat, ale pokud si myslíte, že vypadá jak je neznáte, můžete použít název "fiktivní" – právě nepoužíváte, který může být také použit v definici funkce.Pokud nechcete dát typ na enable_if, je standardně nastavena na neplatný a je zcela přiměřené, protože není důležité co Dummy je.Tento postup funguje pro vše, včetně operátory převodu a variadic konstruktory.
Scénář 4 funguje v konstruktory, které nemají návratové typy a tím řeší omezení zalamování scénář 1.Scénář 4 je však omezena na argumenty funkce bez použití šablon, které nejsou vždy k dispozici.(Použití scénář 4 na argument funkce bez vizuálního vzhledu zabrání srážky argument šablony z práce na něm).
enable_ifje výkonný, ale také nebezpečné, pokud je chybná.Vzhledem k tomu, že jejím účelem je aby kandidáty před přetížení rozlišení zmizí, když je zneužit, jejích účinků může být velmi matoucí.Zde jsou některá doporučení:
Nepoužívejte enable_if Chcete-li vybrat mezi implementacemi v době kompilace.Není někdy napsat jednu enable_if pro CONDITION a druhou pro !CONDITION.Místo toho použijte Pult značky vzorek – například algoritmus, který vybere implementace v závislosti na úspěších iterátorů jim právě udělen.
Nepoužívejte enable_if Chcete-li vynutit požadavky.Pokud chcete ověřit parametry šablony a ověření se nezdaří, způsobit chybu namísto výběru jiné implementace, použití static_assert.
Použití enable_if Pokud máte sadu přetížení, díky které jinak dobrý kód nejednoznačný.Nejčastěji k tomu dochází v Implicitním převodem konstruktory.
Příklad
Tento příklad vysvětluje, jak funkce šablony STL std::make_pair() využívá enable_if.
void func(const pair<int, int>&);
void func(const pair<string, string>&);
func(make_pair("foo", "bar"));
V tomto příkladu make_pair("foo", "bar") vrátí pair<const char *, const char *>.Přetížení rozlišení musí určit, která func() chcete.pair<A, B>má implicitně převod konstruktoru z pair<X, Y>.To není nový, byl v C ++ 98.Nicméně v C ++ 98/03, implicitně převod konstruktoru podpis vždy existuje, i když je pair<int, int>(const pair<const char *, const char *>&).Přetížení rozlišení není péči, že pokus o vytvoření instance tohoto konstruktoru Rozpad horribly protože const char * není implicitně převést na int; pouze na podpisy před funkce, které jsou vytvořeny definice vyhledávání.Příklad tedy dvojznačné, protože existují podpisy pro převod pair<const char *, const char *> obou pair<int, int> a pair<string, string>.
C++11 solved this ambiguity by using enable_if to make sure pair<A, B>(const pair<X, Y>&) exists only when const X& is implicitly convertible to A and const Y& is implicitly convertible to B.Díky rozlišení přetížení určit, který pair<const char *, const char *> není převoditelná na pair<int, int> a že přetížení, která přijímá pair<string, string> je životaschopné.
Požadavky
Záhlaví: < type_traits >
Obor názvů: std