Если аргумент тривиально конструируем и не изменяется, передайте по значению. Соглашение о вызовах автоматически передает большие структуры по ссылке.
struct alignas(4096) page {unsigned char bytes[4096];};
[[nodiscard]] constexpr page operator^(page l, page r) noexcept {
for (int i = 0; i < 4096; ++i)
l.bytes[i] = l.bytes[i] ^ r.bytes[i];
return l;
}
Аргументы, которые были изменены и / или возвращены по неконстантной ссылке, должны передаваться по неконстантной ссылке.
constexpr page& operator^=(page& l, page r) noexcept {return l = l ^ r;}
Передать любой аргумент, возвращенный с семантикой константных ссылок, по константной ссылке.
using buffer = std::vector<unsigned char>;
[[nodiscard]] std::string_view to_string_view(const buffer& b) noexcept {
return {reinterpret_cast<const char*>(b.data()), b.size()};
}
Передать любой аргумент, глубоко скопированный в другой тип по константной ссылке.
[[nodiscard]] std::string to_string(const buffer& b) {
return std::string{to_string_view(b)};
}
Передайте любой нетривиально конструируемый, неизмененный и не глубоко скопированный аргумент с помощью константной ссылки.
std::ostream& operator<<(std::ostream& os, const buffer& b) {
os << std::hex;
for (const unsigned short u8 : b)
os << u8 << ',';
return os << std::dec;
}
Передать любой аргумент, глубоко скопированный в значение того же типа по значению. Нет смысла передавать по ссылке аргумент, который все равно копируется, и конструктор для возвращаемой копии оптимизируется. См https://en.cppreference.com/w/cpp/language/copy_elision
[[nodiscard]] buffer operator^(buffer l, const buffer& r) {
const auto lsize = l.size();
const auto rsize = r.size();
const auto minsize = std::min(lsize, rsize);
for (buffer::size_type i = 0; i < minsize; ++i)
l[i] = l[i] ^ r[i];
if (lsize < rsize)
l.insert(l.end(), r.begin() + minsize, r.end());
return l;
}
Сюда также входят функции шаблонов.
template<typename T>
[[nodiscard]]
constexpr T clone(T t) noexcept(std::is_nothrow_constructible_v<T, T>) {
return t;
}
В противном случае получить аргументы типа параметра шаблона путем пересылки ссылки (&&
). Примечание: &&
имеет семантику перенаправления (универсальной) ссылки только в аргументах типа параметра шаблона и / или для auto&&
или decltype(auto)&&
.
template<typename T>
constexpr bool nt = noexcept(std::is_nothrow_constructible_v<int, T&&>);
template<typename T>
[[nodiscard]]
constexpr int to_int(T&& t) noexcept(nt<T>) {return static_cast<int>(t);}
const auto to_int_lambda = [](auto&& t) noexcept(to_int(t)) {return to_int(t);};