Скажем, у меня есть два шаблона для перегрузки operator=
:
class MyClass {
public:
template <typename T>
std::enable_if_t<true == /* a condition */, MyClass&>
operator=(T value) {
std::cout << "Pass by copy" << std::endl;
}
template <typename T>
std::enable_if_t<false == /* a condition */, MyClass&>
operator=(const T &value) {
std::cout << "Pass by reference" << std::endl;
}
};
Какое условие было бы наиболее оптимальным для использования с std::enable_if
?
Я придумал это:
template <typename T>
struct pass_copy_cond : std::conditional<
std::is_fundamental<T>::value ||
std::is_pointer<T>::value ||
(std::is_trivial<T>::value && sizeof(T) < sizeof(void*))
, std::true_type, std::false_type>::type {};
Есть ли способ улучшить состояние?
Не думал об этом. Однако, когда я пытаюсь это сделать, компилятор не может вывести argument T
...
Это хороший момент, вы не сможете напрямую выполнять дедукцию шаблона, и вы не можете явно указать аргументы шаблона для оператора. Вы могли бы идеально перенаправить operator()
на приватную функцию, которая на самом деле реализует поведение, но на данный момент я не уверен, что это все еще стоит того.
Все основные типы и типы указателей также тривиальны. По общему признанию, некоторые фундаментальные типы могут быть больше, чем void*
(указатели на член / функцию-член, хотя они, вероятно, больше, не обнаруживаются std::is_pointer
).
Достаточно быть тривиально копируемым, тривиальная конструируемость по умолчанию не имеет значения. Можно даже привести доводы в пользу того, что одной лишь тривиальной разрушаемости достаточно.
template <class T>
using prefer_copy = std::bool_constant<std::is_trivially_copyable<T>() && sizeof(T) <= sizeof(std::max_align_t)>;
Если ваш компилятор позволяет вам форсировать встраивание (не стандартизировано, но почти каждый компилятор так или иначе это допускает), вы можете делегировать эту единственную общую реализацию и получить ее встраивание.
Если реализация для передачи по значению и по ссылке будет одинаковой, вы можете просто использовать
std::conditional_t
для определения типа аргумента вместо использованияenable_if
. Преимущество в том, что вам нужно написать функцию только один раз, избегая повторений.