Frage

Ich habe den folgenden Code, der kompiliert und funktioniert gut:

template<typename T>
T GetGlobal(const char *name);

template<>
int GetGlobal<int>(const char *name);

template<>
double GetGlobal<double>(const char *name);

Allerdings möchte ich die „default“ Funktion entfernen. Das heißt, ich will alle Anrufe machen GetGlobal , wobei ‚t‘ nicht ein int oder ein Doppel ein Fehler auf.

Zum Beispiel GetGlobal () soll ein Kompilierung Fehler sein.

Ich habe versucht, nur die Standard-Funktion zu löschen, sondern, wie ich dachte, erhielt ich eine Menge Fehler .. So ist es eine Möglichkeit, um es „zu deaktivieren“ und Anrufe nur an den speziellen Versionen der Funktion erlauben?

Danke!

War es hilfreich?

Lösung

Um einen Fehler bei der Kompilierung implementieren als:

template<typename T>
T GetGlobal(const char *name) { T::unimplemented_function; }
// `unimplemented_function` identifier should be undefined

Wenn Sie Boost-verwenden Sie könnten es machen elegantere:

template<typename T>
T GetGlobal(const char *name) { BOOST_STATIC_ASSERT(sizeof(T) == 0); }

C ++ Standard garantiert, dass es keine solche Art ist, die sizeof gleich 0, so dass Sie einen Fehler bei der Kompilierung erhalten.

Wie sbi in seinen Kommentaren schlagen die letzten reduziert werden kann:

template<typename T>
T GetGlobal(const char *name) { char X[!sizeof(T)]; }

Ich bevorzuge die erste Lösung, weil es klare Fehlermeldung gibt (zumindest in Visual C ++) als die andere.

Andere Tipps

Obwohl es eine alte und veraltete Frage, kann es erwähnenswert, dass C++11 dieses Problem gelöst hatte, gelöscht Funktionen:

template<typename T>
T GetGlobal(const char *name) = delete;

template<>
int GetGlobal<int>(const char *name);

UPDATE

Dies wird nicht unter MacOS llvm 8 kompilieren. Es ist aufgrund eines immer noch hängt 4 Jahre alt Defekt (siehe diesen Bug-Report ).

Die folgende Problemumgehung wird das Thema passen (ein static_assert Konstrukt).

template<typename T>
T GetGlobal(const char *name) {
    static_assert(sizeof(T) == 0, "Only specializations of GetGlobal can be used");
}

template<>
int GetGlobal<int>(const char *name);

UPDATE

Visual Studio 15.9 hat den gleichen Fehler. Verwenden Sie die vorherige Abhilfe für sie.

Wenn Sie es nicht implementieren, werden Sie mindestens einen Linker Fehler. Wenn Sie einen Fehler bei der Kompilierung möchten, können Sie dies mit Klasse-Vorlagen:

template<typename T>
struct GlobalGetter;

template<>
struct GlobalGetter<int> {
  static int GetGlobal(const char *name);
};

template<>
struct GlobalGetter<double> {
  static double GetGlobal(const char *name);
};

template<typename T>
T GetGlobal(const char *name)
{
  return GlobalGetter<T>::GetGlobal(name);
}

würde ich vorschlagen, nicht wirklich eine Implementierung zur Verfügung zu stellen, nur eine blanke Erklärung des Verfahrens.

Die andere Möglichkeit wäre, eine Compiler-assert zu verwenden. Boost hat eine Reihe solcher Tiere.

namespace mpl = boost::mpl;
BOOST_MPL_ASSERT((mpl::or_< boost::same_type<T, double>,
                            boost::same_type<T, int> >));

Es gibt auch seine Nachrichtenversion Gegenstück, das helfen würde.

Im Folgenden werden alternative Techniken zur Verwendung von boost:

Deklarieren Sie eine typedef zu einem abhängigen Namen

Das funktioniert, weil Namenssuche für DONT tritt nur bei ‚T‘ ersetzt. Dies ist eine ähnliche (aber legal) Version von dem gegebenen Beispiel von Kirill

template <typename T>
T GetGlobal (const char * name) {
    typedef typename T::DONT CALL_THIS_FUNCTION;
}

Verwenden Sie einen unvollständiger Rückgabetyp

Diese Technik funktioniert nicht für Spezialisierungen, aber es wird für Überlastungen arbeiten. Die Idee ist, dass sein Recht eine Funktion zu deklarieren, die einen unvollständigen Typen zurückgibt, aber nicht zu nennen:

template <typename T>
class DONT_CALL_THIS_FUNCTION GetGlobal (const char * name);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top