Question

J'ai le code suivant qui compile et fonctionne bien:

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

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

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

Cependant, je souhaite supprimer le " défaut " une fonction. C’est-à-dire que je souhaite passer tous les appels à GetGlobal & Lt; t & Gt; où 't' n'est pas un int ou un double une erreur.

Par exemple, GetGlobal < char > () doit être une erreur de compilation.

J'ai essayé de supprimer la fonction par défaut, mais, comme je l'imaginais, j'ai reçu beaucoup d'erreurs. Il existe donc un moyen de & "désactiver &"; et autoriser les appels uniquement vers les versions spécialisées de la fonction?

Merci!

Était-ce utile?

La solution

Pour obtenir une erreur de compilation, implémentez-la en tant que:

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

Si vous utilisez Boost, vous pourriez le rendre plus élégant:

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

C ++ Standard garantit qu’il n’existe aucun type de ce type dont la taille est égale à 0, vous obtiendrez donc une erreur lors de la compilation.

Comme le sbi suggéré dans ses commentaires, le dernier pourrait être réduit à:

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

Je préfère la première solution car elle génère un message d'erreur plus clair (du moins dans Visual C ++) que les autres.

Autres conseils

Bien qu'il s'agisse d'une question ancienne et obsolète, il convient de noter que C++11 avait résolu ce problème à l'aide de fonctions supprimées:

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

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

MISE À JOUR

Ceci ne sera pas compilé sous MacOS llvm 8. Cela est dû à un défaut toujours suspendu âgé de 4 ans (voir ce rapport de bogue . ).

La solution suivante résoudra le problème (à l'aide d'une construction static_assert).

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);

MISE À JOUR

Visual studio 15.9 a le même bogue. Utilisez la solution de contournement précédente pour cela.

Si vous ne l'implémentez pas, vous obtiendrez au moins une erreur de l'éditeur de liens. Si vous souhaitez une erreur lors de la compilation, vous pouvez le faire avec des modèles de classe:

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);
}

Je suggérerais de ne pas fournir réellement d'implémentation, mais simplement une simple déclaration de la méthode.

L’autre option consisterait à utiliser une assertion à la compilation. Boost a un certain nombre de ces bêtes.

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

Il y a aussi son équivalent de version de message, ce qui aiderait.

Les techniques suivantes sont différentes de l’utilisation de boost:

Déclarer une typedef en un nom dépendant

Cela fonctionne parce que la recherche de nom pour DONT ne se produit que lorsque "T" a été remplacé. Ceci est une version similaire (mais légale) de l'exemple donné par Kirill

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

Utiliser un type de retour incomplet

Cette technique ne fonctionne pas pour les spécialisations, mais en cas de surcharge. L’idée est qu’il est légal de déclarer une fonction qui retourne un type incomplet, mais pas de l’appeler:

template <typename T>
class DONT_CALL_THIS_FUNCTION GetGlobal (const char * name);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top