Ich versuche, eine Klasse zu erstellen, die die Konstruktoren von anderen Klassen übernehmen sollte, aber ohne von diesen Klassen selbst zu erben.Wie verwendet man std :: enable_if, um einen variadischen Konstruktor bedingt auszuwählen?
An einem Punkt während der Initialisierung meiner Klasse möchte ich perfekte Weiterleitung verwenden, um ein Objekt des Typs zu erstellen, dessen Konstruktor den angegebenen Argumenten entsprach.
Mit Ausnahme des Standardkonstruktors ohne Argumente dürfen keine Mehrdeutigkeiten auftreten.
Dies ist mein Code:
#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;
}
ich viele Dinge ausprobiert, aber ich kann es einfach nicht funktioniert bekommen.
- Im aktuellen Ansatz
enable_if
nicht automatisch die Vorlage args abziehen (glaube ich) - Da ich den Konstruktor verwenden kann ich nicht
enable_if
auf den Rückgabewert verwenden - einen anderen Standard-Parameter für
enable_if
gewonnen Hinzufügen ‚t Arbeit, weil der Konstruktor ist variadische - Wenn ich entfernen
enable_if
aus den Funktionsargumente der Compiler über ungültige Überlastungen (natürlich) klagt
Gibt es eine elegante Möglichkeit, dieses Problem zu lösen?
Bearbeiten: Die eine implizite Konvertierung, die von der Norm erlaubt ist, sollte nicht in meiner Klasse auftreten.
Eine Lösung, die mit dem obigen Beispiel funktioniert, wäre, einen einzelnen variadischen Konstruktor zu definieren und die Argumente perfekt an eine konditionierte Initialisierungsfunktion weiterzuleiten. Ich möchte jedoch diesen Overhead vermeiden, da Member standardmäßig erstellt werden müssen und dies in anderen Fällen möglicherweise nicht funktioniert.
(Fühlen Sie sich frei, die Frage zu bearbeiten, wenn Dinge klarer gemacht werden)
Gute Frage und ich habe keine Antwort. FWIW, * ohne * variadic templates [funktioniert] (http://coliru.stacked-crooked.com/a/c799960a369ccf7e) unter Verwendung von voreingestellten Parametern. –
Ich fragte nahe Verwandte Frage auch in: http://StackOverflow.com/Questions/18700072/using-SFINAE-ToSelect-Different-Method-Implementations-in-Akla- se-Template.Eine Antwort war auch, stattdessen Spezialisierung zu verwenden :-) – Klaus
Wie ich in einem Kommentar zu Klaus 'Lösung gesagt habe: Nur eine ** benutzerdefinierte Umwandlung wird implizit durchgeführt. Entweder vom String-Literal zu 'std :: basic_string' oder von einem' std :: basic_string' zu Ihrem 'String'-Typ, aber nicht beides. – dyp