Considérons le modèle de fonction suivante:Stratégie automatique d'évaluation Sélection en C++
template<typename T> void Foo(T)
{
// ...
}
sémantique passe par valeur de sens que si T
se trouve être un type intégral, ou au moins un type qui est pas cher à copier. En revanche, l'utilisation de la sémantique de référence par rapport à [const] a plus de sens si T
s'avère être un type coûteux à copier.
Supposons pour une seconde que vous écrivez une bibliothèque. Idéalement, en tant que responsable de la mise en œuvre d'une bibliothèque, votre travail consiste à fournir à vos clients une API propre, à la fois générique et efficace. Comment alors, fournissez-vous une interface générique qui s'adresse aux deux types de stratégies de passage d'argument?
Voici ma première tentative d'obtenir que cela fonctionne:
#include <boost/type_traits.hpp>
template<typename T> struct DefaultCondition
{
enum {value = boost::is_integral<T>::value /* && <other trait(s)> */};
};
template< typename T, class Condition = DefaultCondition<T> > class Select
{
template<bool PassByValue = Condition::value, class Dummy = void> struct Resolve
{
typedef T type;
};
template<class Dummy> struct Resolve<false, Dummy>
{
typedef const T& type;
};
public: typedef typename Resolve<>::type type;
};
Utilisation typique:
template<typename T> class EnterpriseyObject
{
typedef typename Select<T>::type type;
public: explicit EnterpriseyObject(type)
{
// ...
}
};
struct CustomType {};
void Usage()
{
EnterpriseyObject<int>(0); // Pass-by-value.
(EnterpriseyObject<CustomType>(CustomType())); // Pass-by-const-reference.
}
Ceci, bien sûr, rompt indirectement déduction argument de modèle implicite de non-classe modèles:
template<typename T> void Foo(typename Select<T>::type)
{
// ...
}
void Usage()
{
Foo(0); // Incomplete.
Foo<int>(0); // Fine.
}
Cela peut être "fixe" avec la bibliothèque Boost.Typeof
et une macro, à la la WinAPI
:
#define Foo(Arg) ::Foo<BOOST_TYPEOF((Arg))>((Arg))
Bien que ce soit juste un hack quasi-portable.
Comme vous pouvez le voir, mon approche générale n'est pas vraiment satisfaisante dans tous les cas. En tant que programmeur amateur, je n'ai ni l'expérience du monde réel ni l'accès au code de qualité de production pour référence. Je me rends compte aussi que cela peut sembler un mauvais cas d'optimisation prématurée, mais je suis vraiment intéressé par deux choses:
- -vous, ou avez-vous utilisé ce type d'optimisation * dans le passé?
- Est-ce que la bibliothèque
Boost
(ou toute autre bibliothèque publique) offre déjà des fonctionnalités similaires? - Si la réponse à # 1 ou # 2 est un 'oui' - comment le cas du modèle hors classe est-il traité?
- Y a-t-il des pièges évidents que je ne vois pas avec quelque chose comme ça?
- Enfin, est-ce encore une chose saine à faire?
* Non profilé. ;)
allait mentionner http://www.boost.org/doc/libs/1_43_0/doc/html/ref.html – 5ound
@ 5ound: Aussi utile, merci! – chrosph