Я бы предложил использовать sizeof(size_t)
(или sizeof(ptrdiff_t)
), который возвращает «типичный» размер, связанный с вашей машиной, в надежде, что любая переменная этого размера вписывается в регистр. В этом случае вы можете безопасно передать его по значению. Более того, как предлагает @ n314159 (см. Комментарии в конце этого поста), полезно убедиться, что переменная тоже trivialy_copyable
.
Вот демонстрация C ++ 17:
#include <array>
#include <ccomplex>
#include <iostream>
#include <type_traits>
template <typename T>
struct maybe_ref
{
using type = std::conditional_t<sizeof(T) <= sizeof(size_t) and
std::is_trivially_copyable_v<T>, T, const T&>;
};
template <typename T>
using maybe_ref_t = typename maybe_ref<T>::type;
template <typename T>
class Foo
{
public:
Foo(maybe_ref_t<T> t) : _t(t)
{
std::cout << "is reference ? " << std::boolalpha
<< std::is_reference_v<decltype(t)> << std::endl;
}
private:
const T _t;
};
int main()
{
// with my machine
Foo<std::array<double, 1>> a{std::array<double, 1>{}}; // <- by value
Foo<std::array<double, 2>> b{std::array<double, 2>{}}; // <- by ref
Foo<double> c{double{}}; // <- by value
Foo<std::complex<double>> d{std::complex<double>{}}; // <- by ref
}