c++ - 执行 constexpr 运算符重载的指南?

标签 c++ c++11 operator-overloading constexpr c++14

考虑一个简单的 int Wrapper 类,它具有重载的乘法 operator*=operator*。对于“老式”的运算符重载,可以用 operator*= 来定义 operator*,甚至还有像 Boost.Operators 这样的库。及其现代化身df.operators @DanielFrey 为您减少了样板文件。

但是,对于使用新的 C++11 constexpr 进行编译时计算,这种便利就消失了。 constexpr operator* 不能调用 operator*= 因为后者修改了它的(隐式)左参数。此外,还有 no overloading on constexpr ,因此将额外的 constexpr operator* 添加到现有的 operator* 会导致重载解析模糊。

我目前的做法是:

#include <iostream>

struct Wrap
{
    int value;    

    Wrap& operator*=(Wrap const& rhs) 
    { value *= rhs.value; return *this; }

    // need to comment this function because of overloading ambiguity with the constexpr version
    // friend Wrap operator*(Wrap const& lhs, Wrap const& rhs)
    // { return Wrap { lhs } *= rhs; }    

    friend constexpr Wrap operator*(Wrap const& lhs, Wrap const& rhs)
    { return { lhs.value * rhs.value }; }
};

constexpr Wrap factorial(int n)
{
    return n? factorial(n - 1) * Wrap { n } : Wrap { 1 };    
}

// want to be able to statically initialize these arrays
struct Hold
{
    static constexpr Wrap Int[] = { factorial(0), factorial(1), factorial(2), factorial(3) };
};

int main() 
{
    std::cout << Hold::Int[3].value << "\n"; // 6
    auto w = Wrap { 2 };
    w *= Wrap { 3 };
    std::cout << w.value << "\n"; // 6
}

Live output here .我的问题是:

  • operator*=operator* 中的乘法逻辑重复,而不是用 表示 operator*运算符*=
  • 因此,Boost.Operators 不再用于减少编写许多其他算术运算符的样板

问题:这是推荐的 C++11 方式,同时具有运行时 operator*= 和混合运行时/编译时 constexpr 运算符*? C++14 是否将这里的任何内容更改为例如减少逻辑重复?

更新:@AndyProwl 的回答被认为是惯用的,但根据@DyP 的建议,在 C++11 中,可以减少逻辑重复,但代价是额外的任务和违反直觉的风格

    // define operator*= in terms of operator*
    Wrap& operator*=(Wrap const& rhs) 
    { *this = *this * rhs; return *this; }

最佳答案

我找不到 C++11 的惯用解决方案(尽管作为一种变通方法,DyP's suggestion 对我来说似乎可以接受)。

然而,在 C++14 中,constexpr does not imply const (参见 C++14 标准草案 n3690 的附件 C.3.1),您可以简单地将 operator *=operator * 定义为 constexpr,并像往常一样根据前者定义后者:

struct Wrap
{
    int value;    

    constexpr Wrap& operator *= (Wrap const& rhs) 
    { value *= rhs.value; return *this; }

    friend constexpr Wrap operator * (Wrap const& lhs, Wrap const& rhs)
    { return Wrap(lhs) *= rhs; }    
};

这里是 live example ,上面的程序是在 Clang 上使用 -std=c++1y 编译的 - 不幸的是,GCC 似乎还没有实现这个规则。

关于c++ - 执行 constexpr 运算符重载的指南?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17744842/

相关文章:

c++ - 为什么 std::is_array 对 std::array 返回 false?

c++ - 将 std::set 传递给 C++ 中的方法

c++ - 移动 basic_iostream 时 basic_ostream 基会发生什么变化?

c++ - 基于 : issue with constness 范围内的自定义迭代器

python - 从一组电阻值中找出最小电阻数的算法。 (C++ 或 Python)

c++ - 如何按降序打印数组?

c++ - 编译时和运行时数组的一个模板类(名称),代码重复很少

c++ - 在 C++ 中重载 << 运算符

c++ - 使用 strchr 重载 >>

c++ - 将指向模板函数的指针作为函数参数传递?