模板参数数组

Template Parameter Array

我正在尝试创建一个 class,它使用数组的值作为 value/type 模板参数。见下文

template< std::array<bool, M> arr>
class gf {
...
};

我相信我这样做的理由是明智的。 class 为加法和乘法实现运算符重载。只有当 class 的实例使用与 arr.

相同的值和大小实例化时,这些操作才被明确定义

一个用例示例:

std::array<bool,3> p1 = {0,0,1};
std::array<bool,3> p2 = {0,1,1};

gf<p1> a;
gf<p1> b;
gf<p2> c;

auto out1 = a + b; // works as both instances use p1
auto out1 = a + c; // Compiler error as we're adding incompatible types

我目前的解决方法是将 arr 传递给构造函数调用,并在组合任何不兼容的类型时抛出错误。我希望有更好的方法来做到这一点,谢谢!

编辑: 此外,任何其他可能实现相同目标的设计模式都将受到欢迎。我不喜欢使用模板专业化,但它是我熟悉的工具!

纯粹从技术角度来说,你可以(1)传递静态存储的constexpr数组的地址作为非类型模板参数的持续时间:

#include <array>

template<const auto& arr>
struct gf {
    gf& operator+=(const gf& /* rhs */) {
        // ...
        return *this;
    }
};

template<const auto& arr>
auto operator+(gf<arr> lhs, const gf<arr>& rhs) {
    lhs += rhs;
    return lhs;
}

int main() {
    // As we want to use the address of the constexpr std::array
    // at compile time, it needs to have static storage duration.
    static constexpr std::array<bool, 3U> p1{{0, 0, 1}};
    static constexpr std::array<bool, 3U> p2{{0, 1, 1}};
    
    gf<p1> a;
    gf<p1> b;
    gf<p2> c;
    
    auto out1 = a + b;  // OK.
    //auto out2 = a + c;  // Error: incompatible types.
}

这样 gf class 具有唯一数组对象的模板的每个实例化都将成为唯一类型(/specialization)。

这依赖于 C++17 的 auto 作为模板参数;对于类似的 C++11 方法:

#include <array>

template<std::size_t M, const std::array<bool, M>& arr>
struct gf {
    gf& operator+=(const gf& /* rhs */) {
        // ...
        return *this;
    }
};

template<std::size_t M, const std::array<bool, M>& arr>
gf<M, arr> operator+(gf<M, arr> lhs, const gf<M, arr>& rhs) {
    lhs += rhs;
    return lhs;
}

int main() {
    // As we want to use the address of the constexpr std::array
    // at compile time, it needs to have static storage duration.
    static constexpr std::array<bool, 3U> p1{{0, 0, 1}};
    static constexpr std::array<bool, 3U> p2{{0, 1, 1}};
    
    gf<3U, p1> a;
    gf<3U, p1> b;
    gf<3U, p2> c;
    
    auto out1 = a + b;  // OK.
    //auto out2 = a + c;  // Error: incompatible types.
}

(1) 这个答案不会以任何方式试图将其呈现为任何一种 good 方法来解决 XY 式问题OP.