【问题标题】:When to pass by copy / reference?何时通过复制/引用传递?
【发布时间】:2019-09-01 05:19:22
【问题描述】:

假设我有两个模板用于 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 {};

有什么办法可以改善吗?

【问题讨论】:

  • 如果按值传递和按引用传递的实现相同,您可以只使用std::conditional_t 来确定参数类型,而不是使用enable_if。优点是你只需要编写一次函数,避免自己重复。
  • 没想到。但是,当我尝试它时,编译器无法推断出argument T...
  • 这点很好,你不能直接进行模板推导,也不能显式地为运算符提供模板参数。您可以将 operator() 完美地转发到实际实现该行为的私有函数,但那时我不确定它是否仍然值得。

标签: c++ performance parameter-passing template-meta-programming


【解决方案1】:

有些检查是多余的:

所有基本类型和指针类型也是微不足道的。诚然,一些基本类型可能比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)>;

您将编写两次实现

如果你的编译器允许你强制内联(不是标准化的,但几乎每个编译器都允许它),你可以委托给那个单一的通用实现并将其内联。

【讨论】:

    猜你喜欢
    • 2012-03-30
    • 1970-01-01
    • 2018-02-11
    • 2013-11-21
    • 2011-04-07
    • 1970-01-01
    • 2021-05-20
    相关资源
    最近更新 更多