Tengo una plantilla que se ve así
template <typename T> class Foo
{
public:
Foo(const T& t) : _t(t) {}
private:
const T _t;
};
¿Existe una forma inteligente de metaprogramación de plantillas para evitar el uso de una referencia constante en los casos en que el tipo de argumento es trivial como un bool o char? me gusta:
Foo(stl::smarter_argument<T>::type t) : _t(t) {}
Foo
.Respuestas:
Creo que el rasgo de tipo correcto es
is_scalar
. Esto funcionaría de la siguiente manera:Editar:
Lo anterior sigue siendo un poco anticuado, gracias @HolyBlackCat por recordarme esta versión más concisa:
fuente
is_fundamental
funcionaria tambien?= void
significa que tiene un tipo predeterminado que es nulo, por lo que usarsmarter_argument<T>
es realmentesmarter_argument<T, void>
. Dejé un nombre para este argumento, ya que no lo necesitamos, por lo tanto,class = void
sin un nombre. Es importante que,std::enable_if_t
en caso de que esté habilitado, también se anule para que coincida con el tipo predeterminado.template <typename T> using smarter_argument = std::conditional_t<std::is_scalar_v<T>, T, const T &>;
.Sugeriría usar
sizeof(size_t)
(osizeof(ptrdiff_t)
) que devuelve un tamaño "típico" relacionado con su máquina con la esperanza de que cualquier variable de este tamaño encaje en un registro. En ese caso, puede pasarlo de forma segura por valor. Además, como lo sugiere @ n314159 (ver comentarios al final de esta publicación), es útil asegurarse de que la variable también lo seatrivialy_copyable
.Aquí hay una demostración de C ++ 17:
fuente
struct Foo { void bar(){ }; int i; }; std::cout << sizeof(&Foo::i) << std::endl; //prints 8 std::cout << sizeof(&Foo::bar) << std::endl; //prints 16
<=
lugar de==
, en la mayoría de las máquinas, su código actual toma unchar
ejemplo como referencia si lo veo bien.T
se puede copiar trivialmente. Por ejemplo, un puntero compartido es solo dos veces el tamaño desize_t
mi plataforma y se puede implementar con un solo puntero, reduciéndolo al mismo tamaño. Pero definitivamente desea tomar shared_ptr por const ref y no por valor.Haría uso de la palabra clave C ++ 20
requires
. Así:Puede ejecutar el código en línea para ver el siguiente resultado:
fuente