Qual è il vantaggio di std :: enable_if rispetto a static_assert per i modelli di classe?
Mi chiedevo quale fosse il vantaggio di std::enable_ifoltre static_assertsper impedire la creazione di istanze del modello. Questa risposta suggerisce, che std::enable_ifconsente SFINAE , che è un argomento convincente nel caso dei modelli di funzione .
Tuttavia questo argomento è legittimo per i modelli di classe (e per i modelli di variabili )? Per quanto ne so, non è coinvolta alcuna risoluzione del sovraccarico, rendendo SFINAE - ancora una volta, per quanto ne so - non rilevante, ma potrei sbagliarmi. In caso affermativo, puoi citare un esempio?
In caso contrario, presumo static_assertche sia la soluzione migliore per il problema dato (impedendo l'istanza del modello) nel caso di modelli di classe, poiché è probabilmente più esplicito, conciso e leggibile e consente un messaggio di errore personalizzato. È corretto o mi manca un punto diverso da SFINAE?
Risposte
Esempio di come sovraccaricare le classi utilizzando SFINAE:
#include <type_traits>
#include <iostream>
template <typename, typename = void>
struct Foo;
template <typename Bar>
struct Foo <Bar, typename std::enable_if<std::is_same<Bar,int>::value>::type>
{
Foo ()
{
std::cout << "Hello ";
}
};
template <typename Bar>
struct Foo <Bar, typename std::enable_if<std::is_same<Bar,bool>::value>::type>
{
Foo ()
{
std::cout << "world!\n";
}
};
int main()
{
Foo<int>();
Foo<bool>();
}
Per i casi in cui non si desidera eseguire il sovraccarico ma si desidera comunque limitare a un insieme di tipi, sono d'accordo che:
template <typename Bar>
class Foo
{
static_assert(
std::is_same<Bar,int>::value ||
std::is_same<Bar,bool>::value,
"Bar must be bool or int");
// class stuff
};
... è più chiaro e più semplice di:
template <typename Bar,
typename std::enable_if<
std::is_same<Bar,int>::value ||
std::is_same<Bar,bool>::value,
bool>::type = true>
class Foo
{
// class stuff
};
... soprattutto perché con la seconda opzione il compilatore fa riferimento agli Foooggetti con il loro primo argomento e il loro secondo argomento ( true, nel nostro caso), che possono essere misteriosi per l'utente. Inoltre, è più complicato se si desidera che un'intestazione gestisca la classe con solo una sua dichiarazione leggera (vedere come farlo qui ).
Tuttavia questo argomento è legittimo per i modelli di classe (e per i modelli di variabili)? Per quanto ne so, non è coinvolta alcuna risoluzione del sovraccarico, rendendo SFINAE - ancora una volta, per quanto ne so - non rilevante, ma potrei sbagliarmi. In caso affermativo, puoi citare un esempio?
Puoi specializzare i modelli di classe e SFINAE può essere utilizzato per scegliere tra le specializzazioni. Impedirà anche la creazione di istanze di tale classe / specializzazione (per allora, forse mal formata), invece di non riuscire a compilare a causa di static_assert.
std :: enabled_if viene utilizzato in SFIANE per la specializzazione di classi, metodi e .... static_assert viene utilizzato per controllare un contratto in fase di compilazione e fornire un utile messaggio di errore.