Ich glaube, ich habe eine ideale Lösung. Es erfordert nur, dass die Testfunktion geändert wird, so dass SmartPtr und Variant alleine gelassen werden, was ideal ist. Es wird eine nicht definierte überarbeitete Testversion hinzugefügt, die über Spezialisierungen für bool und nullptr verfügt, die definiert sind. Dadurch werden bool und nullptr direkt an die gewünschte Spezialisierung gesendet, Linkfehler werden jedoch bei anderen nicht behandelten Typen verursacht. Ich bin froh, dass das funktioniert hat, denn ich bin mir selbst in vielen Formen begegnet. Ich wünschte, du könntest explizite Funktionsparameter verwenden !!
habe ich die Idee von hier: C++ templates that accept only certain types
using namespace std;
class Object
{
public:
};
class Variant
{
public:
Variant(bool b) : _b(b) { }
private:
bool _b;
};
template<typename T>
class SmartPtr
{
public:
SmartPtr(std::nullptr_t null) { p_ = nullptr; }
template<typename Y>
SmartPtr(Y* p) { p_ = p; }
private:
T* p_;
};
class Obj
{
public:
void test(SmartPtr<Object> here /*p*/) {
cout << "smartptr version!" << endl;
}
void test(Variant /*v*/) { cout << "variant version!" << endl; }
template<typename T> void test(T t);
template<>
void test<bool>(bool b) {
cout << "bool specialization" << endl;
test(Variant(b));
}
template<>
void test<std::nullptr_t>(std::nullptr_t null) {
cout << "nullptr specialization" << endl;
test(SmartPtr<Object>(nullptr));
}
};
int main(int argc, const char *argv[])
{
Obj o;
Obj c;
Object object;
//o.test(3); // Gives link error LNK2019
o.test(Variant(true)); // calls Variant version
o.test(SmartPtr<Object>(&object)); // calls SmartPtr version
o.test(nullptr); // dispatched to SmartPtr version by nullptr specialization
o.test(true); // dispatched to Variant version by bool specialization
o.test(false); // dispatched to Variant version by bool specialization
return 0;
}
ich schon mit etwas nicht ideal beantwortet hatte, also lasse ich diese Antwort in Takt wie das, was folgt:
======= ==================================
Ich habe keine ideale Lösung Hier, und ich kenne nicht die Einschränkungen, die Sie auf Ihrem Code haben, so dass dies für Sie nicht von Nutzen sein kann, aber das Folgende ist sinnvoll. Es verbietet es dem Code, zur Kompilierzeit nullptr zu verwenden und verlässt sich auf eine globale null_smart-Konstante, die in allen Fällen verwendet wird, in denen der Aufrufer einfach kein Interesse daran zeigt, ein Objekt zu übergeben.
#include <iostream>
using namespace std;
class Object
{
public:
};
class Variant
{
public:
Variant(bool b) : _b(b) { }
private:
Variant(std::nullptr_t) {};
private:
bool _b;
};
template<typename T>
class SmartPtr
{
public:
SmartPtr() { p_ = nullptr; }
template<typename Y>
SmartPtr(Y* p) { p_ = p; }
private:
T* p_;
};
class Obj
{
public:
void test(SmartPtr<Object> /*p*/) { cout << "smartptr version!" << endl; }
void test(Variant /*v*/) { cout << "variant version!" << endl; }
};
const SmartPtr<Object> null_smart;
int main(int argc, const char *argv[])
{
Obj o;
o.test(null_smart); // calls SmartPtr version, without interest in passing object
o.test(true); // calls Variant version
o.test(false); // calls Variant version
return 0;
}
Es ist sauberer als das wahre/Variant (false) Problem, aber immer noch ein bisschen auf der Seite pingelig.
Verschiedene Compiler behandeln diesen Code anders. g ++ (C++ 1y) schlägt bei "nullptr" und "false" fehl. clang (C++ 1y) schlägt bei "nullptr" fehl. Verwandte Frage: http://stackoverflow.com/questions/17501942/false-implicitly-convert-to-null-pointer/ – zch
Ich denke, dass Standard Compiler sollte den gesamten Code akzeptieren ('nullptr_t -> SmartPtr' ist besser als 'nullptr_t -> bool -> Variante' und 'bool -> nullptr_t -> SmartPtr' ist ungültig), aber ich schätze, es hilft dir nicht viel. Ich würde empfehlen, separate Funktionsnamen zu verwenden. – zch
@zsh: Ich benutze sowohl clang und g ++ mit std = C++ 11 auf Linux als auch vc12 auf Windows, die Fehlermeldung ist die gleiche. Unglücklicherweise kommt eine andere Benennung nicht in Frage, da der Code vorher funktioniert hat und ich versuche, den nullptr_t-Konstruktor für die SmartPtr-Klasse einzuführen, der die Kompilierung fehlschlägt. – mgr