带有方法参数的元编程

Meta-Programming with a Method Parameter

我正在编写一个 pair 包装器。出于这个问题的目的,它可以简化为:

using namespace std;

template <class T1, class T2>
class myPair {
    pair<T1, T2> member;
public:
    myPair() = default;
    myPair(T1 x, T2 y) : member(make_pair(x, y)) {}
};

我希望能够将 myPair 视为大小为 2 的可索引容器。为此,我显然需要为 myPair 编写一个索引运算符。我想做这样的事情,但是我的 return 类型将取决于方法参数,我不能在元编程中使用方法参数。

auto myPair::operator[](int index) {
    static_assert(index >= 0 && index < 2, "Index out of range");

    return get<index>(*this);
}

显然我可以通过提供 get 函数以与 pair 相同的方式解决这个问题,但我希望能够使用索引运算符语法。有什么方法可以专门化函数模板或使用方法参数对模板的 return 类型进行元编程?

不,这不可能。成员函数 operator[] 接受非 constexpr 对象,因此几乎不可能进行编译时类型检测。

出于同样的原因,这也会使 static_assert 无法编译。

几乎可能。整型文字不能直接用作常量表达式,但可以包装在一个,例如模板实例化中。

template <int> struct idx_ {};

template <char... C>
auto operator ""_i () {
    return idx_<(C - '0')...>{};
}

template <class T1, class T2>
class myPair {
    std::pair<T1, T2> member;
public:
    myPair() = default;
    myPair(T1 x, T2 y) : member(std::make_pair(x, y)) {}

    T1 &operator [] (idx_<0>) {
        return member.first;
    }

    T2 &operator [] (idx_<1>) {
        return member.second;
    }
};

int main() {
    myPair<int, std::string> mp(42, "Hi");
    std::cout << mp[0_i] << ", " << mp[1_i] << '\n';
}

输出:

42, Hi

Live on Coliru

您可以使用 std::intergral_constant

template <std::size_t N>
const auto& operator[](std::integral_constant<std::size_t, N>) const {
    static_assert(N < 2, "Index out of range");

    return std::get<N>(member);
}

template <std::size_t N>
auto& operator[](std::integral_constant<std::size_t, N>) {
    static_assert(N < 2, "Index out of range");

    return std::get<N>(member);
}

Live Demo