Sto provando a creare una classe che dovrebbe ereditare i costruttori da altre classi ma senza ereditare da quelle stesse classi.Come utilizzare std :: enable_if per selezionare condizionatamente un costruttore variadic?
A un certo punto durante l'inizializzazione della mia classe, voglio utilizzare l'inoltro perfetto per creare un oggetto del tipo il cui costruttore ha abbinato gli argomenti dati.
Tranne che per il costruttore predefinito senza argomenti, non ci devono essere ambiguità.
Questo è il mio codice:
#include <string>
using namespace std;
//NOTE: this class is just an example to demonstrate the problem
class String {
public:
//default constructor to prevent ambiguity
String() {}
//construct from wstring
template<typename... Args>
String(enable_if<is_constructible<wstring, Args...>::value, Args>::type&&... args) : ws(forward<Args>(args)...) {}
//construct from string
template<typename... Args>
String(enable_if<is_constructible<string, Args...>::value, Args>::type&&... args) : s(forward<Args>(args)...) {}
private:
string s;
wstring ws;
};
void foo(const String& string) {
}
int main()
{
foo(L"123");
foo("123");
return 0;
}
Ho provato molte cose, ma non riesco proprio a farlo funzionare.
- Nell'approccio corrente
enable_if
non riesce a detrarre automaticamente le args template (credo) - Da quando uso il costruttore non posso usare
enable_if
sul valore di ritorno - aggiunta di un altro parametro predefinito per
enable_if
Won 't lavoro perché il costruttore è variadic - Quando rimuovo
enable_if
dagli argomenti della funzione il compilatore si lamenta sovraccarichi su invalidi (ovviamente)
Esiste un modo elegante per risolvere questo problema?
Modifica: L'unica conversione implicita consentita dallo standard non dovrebbe verificarsi nella mia classe. [codice di esempio modificato]
Una soluzione che funziona con l'esempio precedente sarebbe definire un singolo costruttore variadic e perfezionare avanti gli argomenti di una funzione di inizializzazione condizionata. Tuttavia, vorrei evitare questo sovraccarico perché i membri devono essere costruiti di default e questo potrebbe non funzionare in altri casi.
(Sentitevi liberi di modificare la domanda se le cose possono essere fatte più chiare)
Buona domanda e non ho una risposta. FWIW, * senza modelli * variadic [funziona] (http://coliru.stacked-crooked.com/a/c799960a369ccf7e) usando i parametri predefiniti. –
Ho chiesto la domanda correlata anche in: http://stackoverflow.com/questions/18700072/using-sfinae-to-select-different-method-implementations-in-a-clase-template.Una risposta era anche usare la specializzazione invece :-) – Klaus
Come ho detto in un commento alla soluzione di Klaus: Solo ** una ** conversione definita dall'utente viene eseguita implicitamente. Sia dalla stringa letterale a 'std :: basic_string' o da una' std :: basic_string' al tuo tipo 'String', ma non entrambi. – dyp