Ci scusiamo per fuorviante nell'ultima risposta, ho pensato per un momento che sarebbe stato più semplice. Quindi cercherò di fornire una soluzione completa qui. L'approccio generale per risolvere questo tipo di problemi è quello di scrivere un modello tratti aiutante e utilizzarlo insieme a enable_if
(sia C++ 11, spinta o implementazione manuale) per decidere una classe di specializzazione:
Trait
Un approccio semplice, non necessariamente il migliore, ma semplice da scrivere sarebbe:
template <typename T>
struct has_nested_Vec {
typedef char yes;
typedef char (&no)[2];
template <typename U>
static yes test(typename U::Vec* p);
template <typename U>
static no test(...);
static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};
l'approccio è semplice, fornisce due funzioni template, che i tipi di ritorno di diverse dimensioni. Uno dei quali accetta il tipo nidificato Vec
e l'altro accetta ellissi. Per tutti quei tipi che hanno un nidificato Vec
il primo sovraccarico è una corrispondenza migliore (i puntini di sospensione sono la peggiore corrispondenza per qualsiasi tipo). Per quei tipi che non hanno un nidificato, Vec
, SFINAE scarterà quel sovraccarico e l'unica opzione rimasta sarà l'ellissi. Quindi ora abbiamo un tratto per chiedere se un tipo ha un tipo nidificato Vec
.
Attiva se
è possibile utilizzare questo da qualsiasi libreria, o si può rotolare il proprio, è abbastanza semplice:
template <bool state, typename T = void>
struct enable_if {};
template <typename T>
struct enable_if<true,T> {
typedef T type;
};
Quando il primo argomento è false
, il modello di base è l'unica opzione, e che non ha un nidificato type
, se la condizione è true
, quindi enable_if
ha un nidificato type
che possiamo usare con SFINAE.
Attuazione
Ora abbiamo bisogno di fornire il modello e la specializzazione che utilizzerà SFINAE solo per quei tipi con un nidificato Vec
:
template<class T, class V = void>
struct Functor {
void operator()() const {
std::cerr << "general" << std::endl;
}
};
template<class T>
struct Functor<T, typename enable_if<has_nested_Vec<T>::value>::type > {
void operator()() const {
std::cerr << "special" << std::endl;
}
};
Ogni volta istanziamo Functor
con un tipo, la il compilatore proverà a utilizzare la specializzazione, che a sua volta istanziare has_nested_Vec
e ottenere un valore di verità, passato a enable_if
. Per quei tipi per i quali il valore è false
, enable_if
non ha un tipo nidificato type
, quindi la specializzazione verrà eliminata in SFINAE e verrà utilizzato il modello di base.
vostro caso particolare
Nel tuo caso particolare in cui sembra che non si ha realmente bisogno di specializzarsi tipo intero, ma solo l'operatore, è possibile mescolare i tre elementi in uno solo: un Functor
che invia a una delle due funzioni interne templated in base alla presenza di Vec
, eliminando la necessità di enable_if
e la classe tratti:
template <typename T>
class Functor {
template <typename U>
void op_impl(typename U::Vec* p) const {
std::cout << "specialized";
}
template <typename U>
void op_impl(...) const {
std::cout << "general";
}
public:
void operator()() const {
op_impl<T>(0);
}
};
Rimosso il tag 'compilatore', viene generalmente utilizzato per domande sul processo di compilazione stesso, mentre questa domanda riguarda il linguaggio C++. –