何时使用复制/引用传递?

4
假设我有两个模板用于重载 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
如果按值传递和按引用传递的实现方式是相同的,那么您可以使用 std::conditional_t 来确定参数类型,而不是使用 enable_if。优点在于您只需编写一次函数,避免重复劳动。 - François Andrieux
没有想到这一点。然而,当我尝试时,编译器无法推断出“参数T”... - Fourmet
这是一个很好的观点,你不能直接执行模板推导,并且你不能显式地为运算符提供模板参数。你可以让operator()完美地转发到一个实际实现行为的私有函数,但此时我不确定它是否仍然值得这样做。 - François Andrieux
1个回答

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)>;

你需要编写两次实现

如果你的编译器允许你强制内联(虽然不标准,但几乎每个编译器都有这种方法),你可以将其委托给这个单一的常见实现并使其内联化。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接