Mam szablon, który wygląda tak
template <typename T> class Foo
{
public:
Foo(const T& t) : _t(t) {}
private:
const T _t;
};
Czy istnieje sprytny sposób metaprogramowania szablonów, aby uniknąć używania stałej referencji w przypadkach, gdy typ argumentu jest trywialny, jak bool lub char? lubić:
Foo(stl::smarter_argument<T>::type t) : _t(t) {}
Foo
.Odpowiedzi:
Myślę, że właściwą cechą jest typ
is_scalar
. To działałoby w następujący sposób:Edytować:
Powyższe jest wciąż trochę oldschoolowe, dzięki @HolyBlackCat za przypomnienie mi o tej bardziej zwięzłej wersji:
źródło
is_fundamental
działał?= void
oznacza, że ma domyślny typ, który jest nieważny, więc użyciesmarter_argument<T>
jest w rzeczywistoścismarter_argument<T, void>
. Odrzuciłem nazwę dla tego argumentu, ponieważ nie jest nam potrzebna, stądclass = void
bez nazwy. Ważne jest, abystd::enable_if_t
w przypadku, gdy jest on włączony, również musi być nieważny, aby pasował do domyślnego typu.template <typename T> using smarter_argument = std::conditional_t<std::is_scalar_v<T>, T, const T &>;
.Sugerowałbym użyć
sizeof(size_t)
(lubsizeof(ptrdiff_t)
), który zwraca „typowy” rozmiar związany z twoim komputerem z nadzieją, że dowolna zmienna tego rozmiaru zmieści się w rejestrze. W takim przypadku możesz bezpiecznie przekazać wartość. Ponadto, jak sugeruje @ n314159 (patrz komentarze na końcu tego postu), warto upewnić się, że zmienna jest równieżtrivialy_copyable
.Oto demo C ++ 17:
źródło
struct Foo { void bar(){ }; int i; }; std::cout << sizeof(&Foo::i) << std::endl; //prints 8 std::cout << sizeof(&Foo::bar) << std::endl; //prints 16
<=
zamiast tego==
, na większości komputerów twój kod przyjmujechar
przykładowo przez odniesienie, jeśli dobrze to widzę.T
go w prosty sposób skopiować. Na przykład wspólny wskaźnik jest tylko dwa razy większy niżsize_t
na mojej platformie i można go zaimplementować za pomocą tylko jednego wskaźnika, dzięki czemu osiągnie ten sam rozmiar. Ale zdecydowanie chcesz wziąć parametr shared_ptr według stałej referencji, a nie wartości.Chciałbym skorzystać ze słowa kluczowego C ++ 20
requires
. Właśnie tak:Możesz uruchomić kod online, aby zobaczyć następujące dane wyjściowe:
źródło