Когда проходить путем копирования / ссылки? - PullRequest
4 голосов
/ 10 апреля 2019

Скажем, у меня есть два шаблона для перегрузки 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 {};

Есть ли способ улучшить состояние?

1 Ответ

1 голос
/ 10 апреля 2019

Некоторые проверки избыточны:

Все основные типы и типы указателей также тривиальны. Следует признать, что некоторые фундаментальные типы могут быть больше, чем 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)>;

Вы будете писать реализацию дважды

Если ваш компилятор разрешает принудительное встраивание (не стандартизировано, но почти каждый компилятор допускает это каким-либо образом), вы можете делегировать эту единственную общую реализацию и получить ее встроенную.

...