Come specializzarsi funzioni membro sulla base di tesi modello di classe
-
30-09-2019 - |
Domanda
Che la questione, dice. Inoltre, è possibile fare questo in linea?
Ecco un piccolo esempio solo per dare un'idea ...
template<typename T>
class Foo {
public:
Foo() :z(0.0) {}
void do( const Foo<T> &f ) {
z = f.z;
}
// specialize 'do' for Foo<int>, possible inline?
private:
T z;
};
Soluzione
È possibile ordinare di ottenere questo comportamento, rendendo la funzione di membro di un modello di funzione membro e utilizzando SFINAE (mancata sostituzione non è un errore). Ad esempio:
template <typename U>
typename std::enable_if<!std::is_integral<U>::value &&
std::is_same<T, U>::value, void>::type
f(const Foo<U>& x)
{
}
template <typename U>
typename std::enable_if<std::is_integral<U>::value &&
std::is_same<T, U>::value, void>::type
f(const Foo<U>& x)
{
}
La prova tratto tipo is_integral
se U
è di tipo intero. Se non lo è, il primo è istanziato; se lo è, il secondo viene istanziata.
I test tratto tipo is_same
a garantire T
e U
sono dello stesso tipo. Questo viene utilizzato per garantire che il modello di funzione di membro non viene creata un'istanza per qualsiasi tipo diverso da Foo<T>
.
In questo esempio fa uso della libreria <type_traits>
C ++ 0x; Boost ha anche una libreria di tipi tratti che è possibile utilizzare, che funziona in gran parte la stessa.
Altri suggerimenti
Non c'è bisogno di fare nulla di complicato. Basta usare il sovraccarico e la delega. Si noti che non possiamo aggiungere un sovraccarico int
, perché quando T
risulta essere int
troppo, questo sarebbe un sovraccarico non valida (due funzioni con la stessa firma)
template<typename T>
class Foo {
public:
Foo() :z(0.0) {}
void doIt(const Foo<T> &f ) {
doItImpl(f);
}
private:
template<typename U>
void doItImpl(const Foo<U> &f) {
z = f.z;
}
void doItImpl(const Foo<int> &f) {
/* ... */
}
private:
T z;
};
In alternativa, per questo caso, si può fare questo per specializzazione
template<typename T>
class Foo {
public:
Foo() :z(0.0) {}
void doIt(const Foo<T> &f ) {
z = f.z;
}
private:
T z;
};
template<>
inline void Foo<int>::doIt(const Foo<int> &f) {
/* ... */
}
Utilizzando la specializzazione in questo modo è possibile solo se tutti gli argomenti di template sono fisse. In altre parole, parzialmente specializzata la funzione membro non è possibile.
Puoi provare a fare qualcosa di simile (non prova, potrebbe non funzionare):
template<typename T>
class Foo {
public:
Foo() :z(0.0) {}
template<typename Ty = T>
void do( const Foo<T> &f ) {
z = f.z;
}
template<>
void do<int>( const Foo<T> &f ) {
//specialized code
}
private:
T z;
};