1

我想将其boost::range::combine用作笛卡尔幂,而不是仅用作产品。

因此,不要写这样的表达式,而是boost::range::combine(myRange, myRange, myRange);写类似myCombine(myRange, 3);.

如何实施?

4

1 回答 1

2

在 C++17 或 C++14 中实现它会更容易和更干净,但是因为你用标记了它,所以这是一个兼容的实现。这是重复多次调用具有相同参数的函数对象 的通用方法。fN

首先,我们需要一种方法来绑定泛型函数对象 f的第一个参数,然后接受任意数量的参数:

template <typename TF, typename T>
struct bound
{
    TF _f;
    T _x;

    template <typename TFFwd, typename TFwd>
    bound(TFFwd&& f, TFwd&& x)
        : _f{std::forward<TFFwd>(f)}, _x{std::forward<TFwd>(x)}
    {
    }

    template <typename... Ts>
    auto operator()(Ts&&... xs)
        -> decltype(_f(_x, std::forward<Ts>(xs)...))
    {
        return _f(_x, std::forward<Ts>(xs)...);
    }
};

template <typename TF, typename T>
auto bind_first(TF&& f, T&& x)
    -> decltype(bound<TF&&, T&&>(std::forward<TF>(f), std::forward<T>(x)))
{
    return bound<TF&&, T&&>(std::forward<TF>(f), std::forward<T>(x));
}

然后,我们需要一个可以多次helper绑定参数的递归:xTN

template <std::size_t TN>
struct helper
{
    template <typename TF, typename T>
    auto operator()(TF&& f, T&& x)
        -> decltype(helper<TN - 1>{}(bind_first(std::forward<TF>(f), x), x))
    {
        return helper<TN - 1>{}(bind_first(std::forward<TF>(f), x), x);
    }
};

template <>
struct helper<0>
{
    template <typename TF, typename T>
    auto operator()(TF&& f, T&& x)
        -> decltype(f(x))
    {
        return f(x);
    }
};

最后,我们可以提供一个漂亮的界面:

template <std::size_t TN, typename TF, typename T>
auto call_with_same_arg(TF&& f, T&& x)
    -> decltype(helper<TN - 1>{}(std::forward<TF>(f), std::forward<T>(x)))
{
    return helper<TN - 1>{}(std::forward<TF>(f), std::forward<T>(x));
}

用法:

int add(int a, int b, int c)
{
    return a + b + c;   
}

int main()
{
    assert(call_with_same_arg<3>(add, 5) == 15);
}

现场魔杖盒示例


这是同一事物的完整 C++17 实现:

template <std::size_t TN, typename TF, typename T>
decltype(auto) call_with_same_arg(TF&& f, T&& x)
{
    if constexpr(TN == 1)
    {
        return f(x);
    }
    else
    {
        return call_with_same_arg<TN - 1>(
            [&](auto&&... xs){ return f(x, std::forward<decltype(xs)>(xs)...); }, x);
    }
}

现场魔杖盒示例


为了完整起见,C++14 实现:

template <std::size_t TN>
struct helper
{
    template <typename TF, typename T>
    decltype(auto) operator()(TF&& f, T&& x)
    {
        return helper<TN - 1>{}(
            [&](auto&&... xs){ return f(x, std::forward<decltype(xs)>(xs)...); }, x);
    }
};

template <>
struct helper<0>
{
    template <typename TF, typename T>
    decltype(auto) operator()(TF&& f, T&& x)
    {
        return f(x);
    }
};

template <std::size_t TN, typename TF, typename T>
decltype(auto) call_with_same_arg(TF&& f, T&& x)
{
    return helper<TN - 1>{}(std::forward<TF>(f), std::forward<T>(x));
}

现场魔杖盒示例

于 2017-03-17T10:15:18.963 回答