J'ai un modèle qui ressemble à ceci
template <typename T> class Foo
{
public:
Foo(const T& t) : _t(t) {}
private:
const T _t;
};
Existe-t-il un moyen de métaprogrammation de modèle avisé pour éviter d'utiliser une référence const dans les cas où le type d'argument est trivial comme un bool ou un char? comme:
Foo(stl::smarter_argument<T>::type t) : _t(t) {}
Foo
.Réponses:
Je pense que le bon trait de type est
is_scalar
. Cela fonctionnerait comme suit:Éditer:
Ce qui précède est encore un peu old-school, merci @HolyBlackCat de me rappeler cette version plus laconique:
la source
is_fundamental
fonctionnerait pas aussi?= void
signifie qu'il a un type par défaut qui est vide, donc l'utilisationsmarter_argument<T>
est en faitsmarter_argument<T, void>
. J'ai laissé un nom pour cet argument car nous n'en avons pas besoin, doncclass = void
sans nom. Il est important que lestd::enable_if_t
cas où il est activé doit également être annulé pour qu'il corresponde au type par défaut.template <typename T> using smarter_argument = std::conditional_t<std::is_scalar_v<T>, T, const T &>;
.Je suggérerais d'utiliser
sizeof(size_t)
(ousizeof(ptrdiff_t)
) qui renvoie une taille "typique" liée à votre machine avec l'espoir que toute variable de cette taille rentre dans un registre. Dans ce cas, vous pouvez le transmettre en toute sécurité par valeur. De plus, comme suggéré par @ n314159 (voir les commentaires à la fin de ce post), il est utile de s'assurer que la variable l'est égalementtrivialy_copyable
.Voici une démo C ++ 17:
la source
struct Foo { void bar(){ }; int i; }; std::cout << sizeof(&Foo::i) << std::endl; //prints 8 std::cout << sizeof(&Foo::bar) << std::endl; //prints 16
<=
place de==
, sur la plupart des machines, votre code actuel prend unchar
exemple par référence si je vois bien.T
est trivialement copiable. Par exemple, un pointeur partagé ne fait que deux fois la taille desize_t
sur ma plate-forme et il peut être implémenté avec un seul pointeur, le ramenant à la même taille. Mais vous voulez certainement prendre le shared_ptr par const ref et non par valeur.J'utiliserais le mot-clé C ++ 20
requires
. Juste comme ça:Vous pouvez exécuter le code en ligne pour voir la sortie suivante:
la source