我晚了几年,但我想从给出的其他答案中就这个话题提供一个对比的观点。考虑为实现支持的各种 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);
}
};
所以......我明白为什么其他答案可能对此持谨慎态度......但我完全认为在可能的情况下使用静态运算符重载是有好处的。我已经看到过去出现了一些关于添加静态运算符重载的各种努力的建议(例如,这个关于静态 operator() 的建议)。也许这值得进行更广泛的讨论,甚至是提议。我当然遇到过很多情况,我认为拥有这个功能会更清晰。命名很难,而且是一个被低估的问题。如果我看到一个带有 form 的函数op_shl(auto a, auto b)
,我会比看到一个 form 的函数更不确定如何处理这个函数:operator<<(auto a, auto b)
. 我们可以就编写好的评论和遵循软件设计的最佳实践提出我们想要的所有论点,但归根结底,静态运算符语法没有歧义。