2015-10-27 6 views
8

Desidero selezionare l'implementazione di una funzione membro (costruttore di copie) basata su un valore di argomento del modello. Suppongo che ci siano due approcci: SFINAE e specializzazione parziale del modello.selezionando il costruttore di copia appropriato in base ai parametri del modello

L'ultimo presunto assomiglia a questo:

#include <iostream> 

template<typename A, bool sw> 
struct B 
{ 
    B() {} 
    B(const B &b); 
}; 

template<typename A> 
B<A, false>::B(const B<A, false> &b) 
{ 
    std::cout << "false\n"; 
} 

template<typename A> 
B<A, true>::B(const B<A, true> &b) 
{ 
    std::cout << "true\n"; 
} 

int main() 
{ 
} 

Esso non può essere compilato: nested name specifier 'B<A, false>::' for declaration does not refer into a class, class template or class template partial specialization.

approccio SFINAE non troppo:

#include <type_traits> 
#include <iostream> 

template<typename A, bool sw> 
struct B 
{ 
    B() {} 

    template<typename U = typename std::enable_if<sw, B>::type> 
    B(const U &b) 
    { 
     std::cout << "true\n"; 
    } 

    template<typename U = typename std::enable_if<!sw, B>::type> 
    B(const U &b) 
    { 
     std::cout << "false\n"; 
    } 
}; 

int main() 
{ 
    { 
     B<int, true> b; 
     auto bc = b; // cout << true 
    } 
    { 
     B<int, false> b; 
     auto bc = b; // cout << false 
    } 
} 

l'errore di compilazione qui è constructor cannot be redeclared e no type named 'type' in 'std::enable_if<false, B<int, false> >'; 'enable_if' cannot be used to disable this declaration.

C'è un modo per risolvere i problemi o altrimenti selezionare il costruttore di copia appropriato in base ai parametri del modello?

+1

non si può fare la specializzazione parziale solo membri di una classe (o struttura) , è necessario specializzare parzialmente la classe completa. –

+1

per il record, uno dei problemi qui è che non si può avere un costruttore di copia basato su modelli (eccetto il fatto che le due firme sono le stesse nel tuo caso, questo può essere risolto), perché una copia implicitamente generata il costruttore vince sempre nella risoluzione di sovraccarico –

risposta

4
template <typename A, bool sw> 
struct B 
{ 
    B() = default; 

    B(const B& b) : B(b, std::integral_constant<bool, sw>{}) {} 

private: 
    B(const B& b, std::true_type) 
    { 
     std::cout << "true\n"; 
    } 

    B(const B& b, std::false_type) 
    { 
     std::cout << "false\n"; 
    } 
}; 

DEMO

0

So che questo è un esempio minimo, ma che c'è di male

B(const B& b) { 
    if(sw) { 
    std::cout << "true\n"; 
    } else { 
    std::cout << "false\n"; 
    } 
} 
+0

Sì, risolve il problema. Ma nel mio caso il costruttore di copia usa o meno (dipende da 'sw') la delega del costruttore. –

1

Come ha detto @Joachim Pileborg in commento, non si può specializzare solo un membro di una classe , devi specializzare l'intera classe. Così il vostro specializzazione parziale sarà simile a questa:

template<typename A, bool sw> 
struct B 
{ 
    B() {} 
    B(const B &b); 
}; 

//Specialize when sw is false 
template<typename A> 
struct B<A, false> 
{ 
    //The constructor in the specialized struct print false 
    B(const B &b) 
    { 
     std::cout << "false\n"; 
    } 
}; 

//Specialize when sw is true 
template<typename A> 
struct B<A, true> 
{ 
    //The constructor in the specialized struct print true 
    B(const B &b) 
    { 
     std::cout << "true\n"; 
    } 
}; 

La soluzione migliore si può ottenere per SFINAE è stato dato da @Piotr Skotnicki

+0

* "perché non puoi ridichiarare un costruttore" * puoi ridichiarle tutte le volte che vuoi (cambiando la firma, come aggiungere un parametro fittizio come 'typename = void'), il problema qui è che, anche se è corretto, un costruttore di copia generato implicitamente verrà sempre selezionato come candidato migliore (perché non è un modello) –

+0

Hai ragione e avrei dovuto dire nella mia risposta che non è possibile ridichiarare un costruttore con la stessa firma. – Pumkko

Problemi correlati