虽然我晚了几年,但我想提供一个与其他答案不同的观点。考虑设计适用于实现支持的各种ABI的特征类的情况。例如,考虑为simd ABI设计特征类的情况:
template<typename T, typename Abi>
struct abi_traits {};
template<>
struct abi_traits<float, sse>
{
using vector_type = __m128;
[[nodiscard]] static constexpr auto operator&(auto a, auto b) noexcept
{
return _mm_and_ps(a, b);
}
};
然后您就可以为每个abi调用运算符重载:
abi_traits<T, Abi>::operator&(a, b);
这可能看起来有些牵强,但考虑一下使用命名函数而不是运算符重载的替代方案:
abi_traits<T, Abi>::and(a, b);
你可能已经知道 "and" 是 C++ 中的一个关键字,因此这段代码无法编译。你需要以某种方式修改名称才能使其工作:
abi_traits<T, Abi>::op_and(a, b);
那么从您的向量类中,您需要像这样提供实现:
template<typename T, typename Abi>
struct simd
{
...
constexpr auto operator&(auto b) noexcept
{
traits<T, Abi>::op_and(this->value, b);
}
};
你当然可以这样做,但是那样你就需要维护和理解程序员强加的混乱命名语法。在我看来,允许静态重载更清晰明了,因为这将更好地展示代码意图:
template<typename T, typename Abi>
struct simd
{
...
constexpr auto operator&(auto b) noexcept
{
traits<T, Abi>::operator&(this->value, b);
}
};
所以……我理解其他答案对此持谨慎态度的原因,但我认为在可能的情况下具有静态运算符重载是有价值的。我曾经看到过一些提案,旨在添加静态运算符重载(例如,
this proposal for static operator())。也许这值得进行更广泛的讨论,甚至可以提出建议。我遇到过许多情况,自己想要拥有这个功能,因为命名很难,这是一个被低估的问题。如果我看到一个形如
op_shl(auto a, auto b)
的函数,我会比看到一个形如
operator<<(auto a, auto b)
的函数更不确定该如何处理这个函数。我们可以就软件设计编写良好的注释并遵循最佳实践进行争论,但归根结底,静态运算符语法没有歧义。
void operator+(X);
?难道你的意思不是X& operator+(X)
吗?也许我是唯一一个感到困惑的人,所以如果我错了,请纠正我。 - E net4operator+
应该返回X
,而不是X&
。 - fredoverflow